HDU
来源:互联网 发布:linux文件夹同步工具 编辑:程序博客网 时间:2024/05/20 07:52
题意:
有n个城市,每个城市里有一个人,互相到各自的城市里去旅游,求旅游路线最大总长度。即给n个点,每个点有一个人,有n-1条有权值的边,求所有人不在原来位置所移动的距离的和最大值。
分析:要求最大值,就让 左边的点跑右边去,右边的点跑左面去。所以每条边,都会被走min{left[num], sum-left[nu,]}*2次
代码如下:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<iomanip>#include<cmath>#include<vector>#include<set>#include<queue>#define INF 0x3f3f3f3fusing namespace std;const int maxn=100000+5; int num[maxn]={0}; int n;class node{public : int v,w; node(){} node(int _v,int _w):v(_v),w(_w){}};vector<node>G[maxn];long long res=0;void dfs(int u,int f)//digui转化为以u为根的子树,u的父节点为f{ num[u]=1; //初始化根节点数目 for(int i=0;i<G[u].size();i++) //遍历u的相邻点 { int v0=G[u][i].v; //节点u的第i个相邻点v0 if(v0!=f) //返回条件 { dfs(v0,u); //把v0的父节点设为u,然后递归转化为以v0为根的子树 num[u]+=num[v0]; res+=(long long )G[u][i].w *2 *(long long )min(num[v0],n-num[v0]);; } }}int main(){ int T; scanf("%d",&T); int kase=0; while(T--) { scanf("%d",&n); for(int i=0;i<=n;i++) G[i].clear(); memset(num,0,sizeof(num)); for(int i=0;i<n-1;i++) { int _u,_v,_w; scanf("%d%d%d",&_u,&_v,&_w); G[_u].push_back(node(_v,_w)); G[_v].push_back(node(_u,_w)); } res=0; dfs(1,0); printf("Case #%d: %lld\n",++kase,res); }}