hdu4118
题目
给你一棵树,树的边有边权,每个节点代表一个人,每个人都要到另一个人的家里且两个人不能同时在一个点,且走的路是最短的路,问走的最多路程的情况的路程是多少。
思路
这道题着眼点不能放到点上,我们要看边,对于一条边,两端有点经过它,考虑点比较少的那一端,经过这条边的点数最多就是少的那端乘以2(出来多少就进去多少,且要根据少的那端的容量),为了让这条边利用最大化,我们就让结果加上2*少的点数*边权,接着就是树形dp了。记得加爆栈代码以及long long。
代码
#pragma comment(linker, "/STACK:10240000000000,10240000000000")
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int tot,head[maxn],n,num[maxn];
ll ans;
struct node
{
int next;
int to;
int w;
} edge[maxn*2];
void addedge(int from,int to,int w)
{
edge[tot].to=to;
edge[tot].next=head[from];
edge[tot].w=w;
head[from]=tot++;
}
void dfs(int u,int fa)
{
num[u]=1;
int v,w;
for(int i=head[u]; ~i; i=edge[i].next)
{
v=edge[i].to;
w=edge[i].w;
if(v==fa) continue;
dfs(v,u);
num[u]+=num[v];
ans+=2*w*(min(n-num[v],num[v]));
}
}
int main()
{
int T;
scanf("%d",&T);
int kase=1;
while(T--)
{
memset(head,-1,sizeof(head));
tot=0;
ans=0;
scanf("%d",&n);
for(int i=0; i<n-1; i++)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);
}
dfs(1,-1);
printf("Case #%d: %I64d\n",kase++,ans);
}
return 0;
}