Codeforces 911F Tree Destruction
先把直径扣出来, 然后每个点都和直径的其中一端组合, 这样可以保证是最优的。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 2e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); int n, deg[N], deptha[N], depthb[N]; vector<int> G[N]; queue<int> que; vector<pair<PII, int>> vc; PII dfs(int u, int fa, int* depth) { if(fa) depth[u] = depth[fa] + 1; else depth[u] = 0; PII ans = mk(depth[u], u); for(auto& v : G[u]) { if(v == fa) continue; ans = max(ans, dfs(v, u, depth)); } return ans; } int main() { scanf("%d", &n); for(int i = 2; i <= n; i++) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); deg[u]++; deg[v]++; } int A = dfs(1, 0, deptha).se; int B = dfs(A, 0, deptha).se; dfs(B, 0, depthb); for(int i = 1; i <= n; i++) if(i != A && i != B && deg[i] == 1) que.push(i); LL ans = 0; while(!que.empty()) { int u = que.front(); que.pop(); if(deptha[u] > depthb[u]) { ans += deptha[u]; vc.push_back(mk(mk(A, u), u)); } else { ans += depthb[u]; vc.push_back(mk(mk(B, u), u)); } for(auto& v : G[u]) if(--deg[v] == 1) que.push(v); } que.push(B); while(!que.empty()) { int u = que.front(); que.pop(); if(u == A) break; ans += deptha[u]; vc.push_back(mk(mk(A, u), u)); for(auto& v : G[u]) if(--deg[v] == 1) que.push(v); } printf("%lld\n", ans); for(auto& t : vc) printf("%d %d %d\n", t.fi.fi, t.fi.se, t.se); return 0; } /* */