题目链接:https://vjudge.net/problem/SPOJ-HOLI
转自:https://www.cnblogs.com/kiuhghcsc/p/5707140.html
题意:有一颗树,每个节点都住着一个人,求让每个人都不在他所住的房子时所有人经过的最长路径长度。
思路:可以围绕着树的重心对称交换,可以使每条边被经过的次数最多,其经过次数最多为2* min(左边的节点数,右边的节点数)。答案为每条边被经过的次数* 边权 *2。
#include <bits/stdc++.h>
#pragma comment (linker, "/STACK:1024000000,1024000000")
using namespace std;
const int maxn=1e5+5;
int n;
struct NODE
{
int to,cost;
NODE(int x=0,int y=0)
{
to=x;
cost=y;
}
};
long long dp[maxn],res;
bool vis[maxn];
vector <NODE> v[maxn];
void dfs(int id,int val)
{
vis[id]=true;
dp[id]=0;
for(int i=0; i<v[id].size(); i++)
{
int to=v[id][i].to;
int w=v[id][i].cost;
if(vis[to])
continue;
dfs(to,w);
dp[id]+=dp[to];
}
dp[id]++;
res+=min(dp[id],n-dp[id])*val*2;
}
int main()
{
int T,a,b,c,kase=0;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=0; i<=n; i++)
{
v[i].clear();
}
res=0;
for(int i=1; i<n; i++)
{
scanf("%d%d%d",&a,&b,&c);
v[a].push_back(NODE(b,c));
v[b].push_back(NODE(a,c));
}
memset(vis,0,sizeof(vis));
dfs(1,0);
printf("Case #%d: %lld\n",++kase,res);
}
return 0;
}