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);    }}
原创粉丝点击