//CAUTION : this template is only suitable with C++17 (above) and home training, do not abuse when practicing offline
#include <bits/stdc++.h>
using namespace std;
//Benq inspires me lol
#define tcT template<class T
#define tcTU tcT, class U
//pairs
#define mp make_pair
#define mt make_tuple
#define ff first
#define ss second
//vectors
#define sz(v) (int)v.size()
#define all(v) begin(v), end(v)
#define rall(v) rbegin(v), rend(v)
#define pb push_back
#define eb emplace_back
#define compact(v) v.erase(unique(all(v)), end(v))
tcT> int lwb(const vector<T>& a, const T& b){ return int(lower_bound(all(a), b) - begin(a)); }
tcT> int upb(const vector<T>& a, const T& b){ return int(upper_bound(all(a), b) - begin(a)); }
//loops (warning : ONLY for int)
#define rep(i, l, r) for(int i = (l); i < (r); ++i)
#define FOR(i, l, r) for(int i = (l); i <= (r); ++i)
//debug
#define dbg(x) "[" #x " = " << (x) << "]"
//data types
using ll = long long;
using db = double;
using ld = long double;
using pi = pair<int, int>;
using pl = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
using vb = vector<bool>;
using vd = vector<db>;
using vc = vector<char>;
using vstr = vector<string>;
using vpi = vector<pi>;
using vpl = vector<pl>;
tcT> using min_heap = priority_queue<T, vector<T>, greater<T>>;
tcT> using max_heap = priority_queue<T>;
//bitwise operations
#define popcount(x) __builtin_popcountll(x) //count bits
#define BIT(k) (1LL << k) //bit k-th
#define all_bits(k) ((1LL << k) - 1) //first k bits on
//functions
tcT> bool minimize(T& a, const T& b){ if(a > b) return a = b, true; return false; }
tcT> bool maximize(T& a, const T& b){ if(a < b) return a = b, true; return false; }
tcT> T ceil_div(T a, T b){ return (a / b) + ((a ^ b) > 0 && a % b); }
tcT> T floor_div(T a, T b){ return (a / b) - ((a ^ b) < 0 && a % b); }
tcTU> T first_true(T lo, T hi, U f){ //if no exist then return hi+1
++hi; assert(lo <= hi);
while(lo < hi){ //[lo, hi)
T mid = (lo + hi) >> 1;
f(mid) ? hi = mid : lo = mid + 1;
}
return lo;
}
tcTU> T last_true(T lo, T hi, U f){ //if no exist then return lo-1
--lo; assert(lo <= hi);
while(lo < hi){ //(lo, hi]
T mid = (lo + hi) >> 1;
f(mid) ? lo = mid : hi = mid - 1;
}
return lo;
}
#ifdef LOCAL //for checking time elapsed
const auto start_time = std::chrono::high_resolution_clock::now();
db time_elapsed(){ return chrono::duration<db>(std::chrono::high_resolution_clock::now() -
start_time).count(); }
#endif //LOCAL
void setIO(){
ios_base::sync_with_stdio(0); cin.tie(0);
#define task "task"
if(fopen(task".inp", "r")){
freopen(task".inp", "r", stdin);
// freopen(task".out", "w", stdout);
}
}
const int MAX = 1e4 + 5;
struct edge{
int u, v, t, c;
edge() : u(), v(), t(), c(){}
edge(int u, int v, int t, int c) : u(u), v(v), t(t), c(c) {}
} edges[MAX];
pair<ll, int> ord[MAX];
int N, M, lab[201];
ll ans = LLONG_MAX, ans_t, ans_c;
vpi cur, ans_edges;
int root(int u){
return lab[u] < 0 ? u : (lab[u] = root(lab[u]));
}
bool join(int u, int v){
u = root(u); v = root(v);
if(u == v) return false;
if(lab[u] > lab[v]) swap(u, v);
lab[u] += lab[v]; lab[v] = u;
return true;
}
pair<ll, ll> solve_ratio(ll a, ll b){ //at + bc
///FUCK THE DISORDER MAY CAUSE GOOFY CASES !!!!!!!
// cout << "input :" << a << ' ' << b << '\n';
rep(i, 0, M){
ord[i] = mp(a * edges[i].t + b * edges[i].c, i);
}
sort(ord, ord + M);
fill(lab, lab + N, -1);
int comps = N;
ll sum_t = 0, sum_c = 0;
cur.clear();
rep(_, 0, M){
int i = ord[_].ss;
if(join(edges[i].u, edges[i].v)){
--comps;
sum_t += edges[i].t;
sum_c += edges[i].c;
cur.eb(edges[i].u, edges[i].v);
}
if(comps == 1) break;
}
// cout << "output : " << sum_t << ' ' << sum_c << "\n\n";
if(sum_t * sum_c < ans){
ans = sum_t * sum_c;
ans_t = sum_t;
ans_c = sum_c;
swap(cur, ans_edges);
}
return mp(sum_t, sum_c);
}
//we receive the point (sum_t, sum_c) that lies on the line with slope (L.c - R.c) / (R.t - L.t)
void solve(const pair<ll, ll>& L, const pair<ll, ll>& R){
pair<ll, ll> M = solve_ratio(L.ss - R.ss, R.ff - L.ff);
if(L == M || M == R) return;
solve(L, M);
solve(M, R);
}
void testcase(int n_case){
cin >> N >> M;
rep(i, 0, M){
int u, v, t, c;
cin >> u >> v >> t >> c;
edges[i] = edge(u, v, t, c);
}
solve(solve_ratio(1, 0), solve_ratio(0, 1));
cout << ans_t << ' ' << ans_c << '\n';
for(auto [u, v] : ans_edges) cout << u << ' ' << v << '\n';
}
int main(){
setIO();
int T = 1;
//cin >> T;
rep(i, 0, T) testcase(i);
#ifdef LOCAL
cerr << '\n' << "Execution time : " << (time_elapsed() * 1000.0) << " ms";
#endif //LOCAL
return 0;
}
Compilation message (stderr)
timeismoney.cpp: In function 'void setIO()':
timeismoney.cpp:95:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
95 | freopen(task".inp", "r", stdin);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |