您的位置:首页 > 其它

魏传之长坂逆袭

2016-07-22 20:29 232 查看
题目描述

众所周知,刘备在长坂坡上与他的一众将领各种开挂,硬生生从曹操手中逃了出去,随后与孙权一起火烧赤壁、占有荆益、成就霸业。而曹操则在赤壁一败后再起不能,终生无力南下。

建安二十五年(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,0<ti<=1000000

手残系列2。。。这道题的意思就是先找出原树中一条长度最大的链,然后要添加最少的数,使得所有链的长度都等于最大链。

那么yy一会儿可以发现一个性质:要是能加的话,肯定先加上面的,因为上面的对下面的都有添加的效果,那么递归一下,就可以算出每个节点最大能加多少。

接下来就脑残+手残了。写完以后,测了几个只有两三层的小数据都对了,就满心以为ok了(这其中也包括第二题位运算括号漏加的因素,导致我一直在调T2)。于是T1愉快的爆0了。。。

晚上我发现,添加的效果是会累积的,也就是说,我添加的话,必须再用另外一个数组来记录当前已被上面累加了多少。。。

数据测试很要紧啊(我的内心是崩溃的)。。。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
int n,x,y,z,tot,TOT,Maxdeep;
ll ans,Max;
int head[500005],Next[1000005],to[1000005],len[1000005];
int HEAD[500005],NEXT[500005],TO[500005];
int deep[500005];
ll c[500005],d[500005];
void add(int x,int y,int z)
{
tot++;
Next[tot]=head[x];
to[tot]=y;
len[tot]=z;
head[x]=tot;
}
void ADD(int x,int y)
{
TOT++;
NEXT[TOT]=HEAD[x];
TO[TOT]=y;
HEAD[x]=TOT;
}
void dfs(int k,int pre,ll s)
{
deep[k]=deep[pre]+1;
ADD(deep[k],k);
Maxdeep=max(Maxdeep,deep[k]);
Max=max(Max,s);
for(int i=head[k];i!=-1;i=Next[i])
if(to[i]!=pre) dfs(to[i],k,s+len[i]);
}
void dp(int k,int pre,ll s)
{
c[k]=Max-s;
for(int i=head[k];i!=-1;i=Next[i])
if(to[i]!=pre)
{
dp(to[i],k,s+len[i]);
c[k]=min(c[k],c[to[i]]);
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
head[i]=-1;
HEAD[i]=-1;
}
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
dfs(1,0,0);
dp(1,0,0);
for(int i=1;i<=Maxdeep;i++)
{
for(int j=HEAD[i];j!=-1;j=NEXT[j])
{
x=TO[j];
ans=ans+c[x]-d[x];
for(int k=head[x];k!=-1;k=Next[k]) d[to[k]]=d[to[k]]+c[x];
}
}
cout<<ans;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: