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;
}

浙公网安备 33010602011771号