正题
题目链接:http://poj.org/problem?id=3585
题目大意
有棵无根树,当你选择一个点为根时,价值就是根节点到所有叶节点的路上的最小权值之和。
解题思路
我们可以先计算一次点1为根时的答案,路上统计答案为didi,然后定义fifi为以i为根节点时的权值。
然后我们再由f1f1转移到后面。我们考虑每一个子节点,
首先我们知道这个父节点转移后价值是dxdx,然后原来的这个子节点的子树,和其他的点都要和wiwi产生影响,具体转移:
fy=dy+min{fx−min{dy,wi},wi}fy=dy+min{fx−min{dy,wi},wi}
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 200010
using namespace std;
struct tree{int to,next,w;
}a[2*N];
int n,in[N],w,ls[N],f[N],d[N],tot,rx,ry,ans,t;
bool v[N];
void addl(int x,int y,int w)
{a[++tot].to=y;a[tot].w=w;a[tot].next=ls[x];ls[x]=tot;in[y]++;
}
void dp(int x)//第一次计算
{v[x]=1;for(int i=ls[x];i!=-1;i=a[i].next){int y=a[i].to;if(v[y]) continue;dp(y);if(in[y]==1) d[x]+=a[i].w;else d[x]+=min(d[y],a[i].w);}
}
void dfs(int x){v[x]=1;for(int i=ls[x];i!=-1;i=a[i].next){int y=a[i].to;if(v[y]) continue;if(in[x]==1) f[y]=d[y]+a[i].w;else f[y]=d[y]+min(f[x]-min(d[y],a[i].w),a[i].w);dfs(y);}
}//换根
int main()
{scanf("%d",&t);while(t--){tot=0;memset(ls,-1,sizeof(ls));memset(f,0,sizeof(f));memset(d,0,sizeof(d));memset(v,0,sizeof(v));memset(in,0,sizeof(in));scanf("%d",&n);for (int i=1;i<n;i++){scanf("%d%d%d",&rx,&ry,&w);addl(rx,ry,w);addl(ry,rx,w);//连边}dp(1);f[1]=d[1];ans=0;memset(v,0,sizeof(v));dfs(1);for(int i=1;i<=n;i++)ans=max(ans,f[i]);printf("%d\n",ans);}
}