POJ - 3585 Accumulation Degree(二次扫描与换根法)
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef pair<int,int> PII;
const int N = 200010, INF = 0x3f3f3f3f;
vector<PII> g[N];
int d[N],f[N],deg[N];
int dfs_d(int u,int fa)
{
if(deg[u]==1)
{
d[u]=INF;
return d[u];
}
d[u]=0;
for(int i=0;i<(int)g[u].size();i++)
{
int j=g[u][i].first;
if(j==fa) continue;
d[u]+=min(g[u][i].second,dfs_d(j,u));
}
return d[u];
}
void dfs_f(int u,int fa)
{
for(int i=0;i<(int)g[u].size();i++)
{
int j=g[u][i].first;
if(j==fa) continue;
if(deg[j]==1) f[j]=min(g[u][i].second,f[u]-g[u][i].second);
else
{
f[j]=d[j]+min(f[u]-min(d[j],g[u][i].second),g[u][i].second);
dfs_f(j,u);
}
}
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int n;scanf("%d",&n);
memset(deg,0,sizeof deg);
for(int i=0;i<=n;i++) g[i].clear();
for(int i=0;i<n-1;i++)
{
int a,b,c;scanf("%d%d%d",&a,&b,&c);
g[a].push_back((PII){b,c});
g[b].push_back((PII){a,c});
deg[a]++,deg[b]++;
}
int root=1;
while(root<=n&°[root]==1) root++;
if(root>n)
{
printf("%d\n",g[n][0].second);
continue;
}
dfs_d(root,-1);
f[root]=d[root];
dfs_f(root,-1);
int res=0;
for(int i=1;i<=n;i++) res=max(res,f[i]);
printf("%d\n",res);
}
return 0;
}