Source: https://oj.vnoi.info/problem/coci1920_r5_putovanje ```cpp= // Goten2308 #include<bits/stdc++.h> using namespace std; using ll = long long; using ii = pair <int, int>; #define fi first #define se second #define mp(x, y) make_pair(x, y) #define pb(x) push_back(x) #define all(x) (x).begin(), (x).end() //#define endl '\n' #define BIT(x, y) ((x >> y) & 1) #define MASK(x) (1 << x) #define MOD 1000000007 #define MULTI_TEST1 template <class T> bool maximize(T& a, T b) { if(a < b) { a = b; return true; } return false; } template <class T> bool minimize(T& a, T b) { if(a > b) { a = b; return true; } return false; } template <class T> void add(T& a, T b) { a += b; if(a >= MOD) a -= MOD; } template <class T> void sub(T& a, T b) { a -= b; if(a <= 0) a += MOD; } const int maxN = (int)2e5 + 7, maxLog = 31 - __builtin_clz(maxN) + 1; int n; struct Edge { int to, c1, c2; Edge (int _to, int _c1, int _c2) { to = _to; c1 = _c1; c2 = _c2; } }; vector <Edge> G[maxN]; namespace subtask2 { struct DSU { vector <int> lab; DSU(int sz) { lab.resize(sz + 1, -1); } int findRoot(int u) { if(lab[u] < 0) return u; return lab[u] = findRoot(lab[u]); } bool join(int u, int v) { u = findRoot(u); v = findRoot(v); if(u == v) return 0; if(lab[u] > lab[v]) swap(u, v); lab[u] += lab[v]; lab[v] = u; return 1; } bool sameSet(int u, int v) { return findRoot(u) == findRoot(v); } }; struct Adj { int f, t, c1, c2; Adj() {} Adj(int _f, int _t, int _c1, int _c2) { f = _f; t = _t; c1 = _c1; c2 = _c2; } }; vector <Adj> adj; void solve() { for(int i = 1; i <= n; i++) { for(auto j : G[i]) if(i < j.to) adj.pb(Adj(i, j.to, j.c1, j.c2)); } ll ans = 0; for(int i = 0; i < adj.size(); i++) { DSU dsu(n); int cnt = 0; for(int j = 0; j < adj.size(); j++) { if(j == i) continue; dsu.join(adj[j].f, adj[j].t); } for(int i = 1; i < n; i++) { if(!dsu.sameSet(i, i + 1)) cnt++; } ans += min(1ll * cnt * adj[i].c1, 1ll * adj[i].c2); } cout << ans << endl; } } namespace subtask3 { const int maxLog = 22; int par[maxN][maxLog + 7], h[maxN], f[maxN]; void DFS(int u, int p) { for(auto nxt : G[u]) { int v = nxt.to; if(v == p) continue; par[v][0] = u; h[v] = h[u] + 1; for(int i = 1; i <= maxLog; i++) par[v][i] = par[par[v][i - 1]][i - 1]; DFS(v, u); } } int LCA(int u, int v) { if(h[u] != h[v]) { if(h[u] < h[v]) swap(u, v); int diff = h[u] - h[v]; for(int i = 0; (1 << i) <= diff; i++) { if(BIT(diff, i)) u = par[u][i]; } } if(u == v) return u; int lg = 31 - __builtin_clz(h[u]); for(int i = lg; i >= 0; i--) if(par[u][i] != par[v][i]) u = par[u][i], v = par[v][i]; return par[u][0]; } void DFS2(int u, int p) { for(auto nxt : G[u]) { int v = nxt.to; if(v == p) continue; DFS2(v, u); f[u] += f[v]; } } void solve() { DFS(1, 0); for(int i = 1; i < n; i++) { int p = LCA(i, i + 1); f[i]++; f[i + 1]++; f[p] -= 2; } DFS2(1, 0); ll ans = 0; for(int i = 1; i <= n; i++) { for(auto nxt : G[i]) { int j = nxt.to; if(h[i] > h[j]) { ans += min(1ll * f[i] * nxt.c1, 1ll * nxt.c2); } } } cout << ans << endl; } } void solve() { cin >> n; for(int i = 1; i < n; i++) { int u, v, c1, c2; cin >> u >> v >> c1 >> c2; G[u].pb(Edge(v, c1, c2)); G[v].pb(Edge(u, c1, c2)); } //if(n <= (int)2e3)subtask2::solve(); //else subtask3::solve(); subtask3::solve(); } signed main(){ #define task "friend" if(fopen(task".inp", "r")){ freopen(task".inp", "r", stdin); freopen(task".out", "w", stdout); } if(fopen("task.inp", "r")){ freopen("task.inp", "r", stdin); //freopen("task.out", "w", stdout); } cin.tie(0)->ios_base::sync_with_stdio(0); int nTest = 1; #ifdef MULTI_TEST cin >> nTest; #endif while(nTest--) { solve(); } return 0; } ```