hdu4118

hdu4118 Holiday's Accommodation
传送门
题意
一棵\(n\)个节点的带有边权的树,每个节点都有一个人,将每个人都换到与当前节点不同的节点,求所有人走过的路径总和的最大值
题解
对于每条边,使得所有人走得最远的方式就是让两边的人互换,为了保证每个人都有位置,交换人数为左右两边人数较少的一方。所以首先通过\(dfs\)预处理,得到以每一个节点为根的子树的顶点个数,然后遍历每条边,找到左边节点数和右边节点数的较小值,将这个值乘上边权再乘上2(左右两边的人交换,都要经过),加入答案

#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<sstream>
#include<cmath>
#include<ctime>
#include<algorithm>
#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define pi acos(-1.0)
#define eps 1e-6
#define lowbit(x) x&(-x)
using namespace std;

const int maxn=100010;
int T,cas,n,dp[maxn];
vector<int> G[maxn];
struct edge{
    int x,y,w;
}e[maxn];

void dfs(int u,int fa){
    dp[u]=1;
    int l=G[u].size();
    for(int i=0;i<l;i++){
        int v=G[u][i];
        if(v!=fa){
            dfs(v,u);
            dp[u]+=dp[v];
        }
    }
}

int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) G[i].clear();
        for(int i=0;i<n-1;i++){
            int x,y,z;
            scanf("%d %d %d",&x,&y,&z);
            G[x].push_back(y);
            G[y].push_back(x);
            e[i].x=x;
            e[i].y=y;
            e[i].w=z;
        }
        dfs(1,-1);
        LL ans=0;
        for(int i=0;i<n-1;i++){
            int m=min(dp[e[i].x],dp[e[i].y]);
            m=min(m,n-m);
            ans+=1ll*e[i].w*m;
        }
        printf("Case #%d: %lld\n",++cas,2*ans);
    }
    return 0;
}
posted @ 2020-08-10 17:37  fxq1304  阅读(59)  评论(0)    收藏  举报