魏传之长坂逆袭 时间限制: 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; }