魏传之长坂逆袭
时间限制: 1 Sec 内存限制: 128 MB
题目描述
众所周知,刘备在长坂坡上与他的一众将领各种开挂,硬生生从曹操手中逃了出去,随后与孙权一起火烧赤壁、占有荆益、成就霸业。而曹操则在赤壁一败后再起不能,终生无力南下。
建安二十五年(220年),曹操已到风烛残年,但仍难忘当年长坂的失误,霸业的破灭。他想如果在刘备逃亡的路中事先布下一些陷阱,便能拖延刘备的逃脱时间了。你作为曹操身边的太傅,有幸穿越到了208年的长坂坡,为大魏帝国贡献一份力,布置一些陷阱。但时空守卫者告诉你你不能改变历史,不能拖增大刘备的最大逃脱时间,但你身为魏武之仕,忠心报国,希望能添加一些陷阱使得刘备不论怎么逃跑所用的时间都一样。
已知共有n个据点,n-1条栈道,保证据点联通。1号据点为刘备军逃跑的起点,当刘备军跑到某个据点后不能再前进时视为刘备军逃跑结束。在任意一个栈道上放置1个陷阱会使通过它的时间+1,且你可以在任意一个栈道上放置任意数量的陷阱。
现在问你在不改变刘备军当前最大逃跑时间的前提下,需要添加最少陷阱,使得刘备军的所有逃脱时间都尽量的大。
输入
第一行一个数n,表示据点个数。
接下来n-1行每行三个数,ai、bi、ti,表示从据点ai通过第i个栈道到bi耗时ti
输出
仅包含一个数,为需要添加的最少陷阱数。
样例输入
3
1 2 1
1 3 3
样例输出
2
提示
【数据规模和约定】
对于 5%的数据,1<=n<=100000,1<=ti<=200000
对于 100%的数据,1<=n<=500000,ti<=1000000
比较每一个分支取子树中最大的那个
一层层加上来
#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll ans;
int Next[1000005],to[1000005],len[1000005];
int n,head[500005],tot,cnt[500005];
void add(int x,int y,int z)
{
Next[tot]=head[x];
to[tot]=y;
len[tot]=z;
head[x]=tot++;
}
ll dfs(int x,int pre)
{
ll ret=0,sum=0;
cnt[x]=0;
for (int i=head[x];i!=-1;i=Next[i])
{
int y=to[i],z=len[i];
if (y==pre) continue;
ll f=dfs(y,x)+z;
cnt[x]++;
ret=max(f,ret);
sum+=f;
}
ans+=ret*cnt[x]-sum;
cnt[x]++;
return ret;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
head[i]=-1;
for (int i=1;i<n;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
int ret=dfs(1,-1);
cout<<ans<<endl;
return 0;
}