感觉有点树形dp的感觉,就是假设a子树及a的点的数量为u,那么a子树之外点的数量就为n-u,使经过边的次数最多,就是min(u,n-u),再乘以到a的权值就可以了。
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <vector> using namespace std; const int maxn=1e5+100; int hade[maxn],dp[maxn]; typedef long long ll; struct note { int to; int next; int w; }aa[maxn*3]; int n,k,t; ll ans; void addage(int fr,int to,int w) { aa[k].to=to; aa[k].w=w; aa[k].next=hade[fr]; hade[fr]=k++; } void init() { memset(hade,-1,sizeof(hade)); memset(dp,0,sizeof(dp)); k=0; ans=0LL; } void dfs(int u,int f,int w) { dp[u]=1; if(hade[u]==-1&&aa[u].to==f) { ans+=(ll)w; return; } for(int i=hade[u];i!=-1;i=aa[i].next) if(aa[i].to!=f) { int v=aa[i].to; dfs(v,u,aa[i].w); dp[u]+=dp[v]; } ans+=(ll)min(n-dp[u],dp[u])*(ll)w; } int main() { scanf("%d",&t); int Case=0; while(t--) { init(); int a,b,z; scanf("%d",&n); for(int i=1;i<n;i++) { scanf("%d%d%d",&a,&b,&z); addage(a,b,z); addage(b,a,z); } dfs(1,0,0); printf("Case #%d: %lld\n",++Case,ans<<1); } return 0; }