题面
Description
【题目背景】
众所周知,刘备在长坂坡上与他的一众将领各种开挂,硬生生从曹操手中逃了出去,随后与孙权一起火烧赤壁、占有荆益、成就霸业。而曹操则在赤壁一败后再起不能,终生无力南下。
建安二十五年(220年),曹操已到风烛残年,但仍难忘当年长坂的失误,霸业的破灭。他想如果在刘备逃亡的路中事先布下一些陷阱,便能拖延刘备的逃脱时间了。你作为曹操身边的太傅,有幸穿越到了208年的长坂坡,为大魏帝国贡献一份力,布置一些陷阱。但时空守卫者告诉你你不能改变历史,不能拖增大刘备的最大逃脱时间,但你身为魏武之仕,忠心报国,希望能添加一些陷阱使得刘备不论怎么逃跑所用的时间都一样。
【问题描述】
已知共有n个据点,n-1条栈道,保证据点联通。1号据点为刘备军逃跑的起点,当刘备军跑到某个据点后不能再前进时视为刘备军逃跑结束。在任意一个栈道上放置1个陷阱会使通过它的时间+1,且你可以在任意一个栈道上放置任意数量的陷阱。
现在问你在不改变刘备军当前最大逃跑时间的前提下,需要添加最少陷阱,使得刘备军的所有逃脱时间都尽量的大。
Input
第一行一个数n,表示据点个数。
接下来n-1行每行三个数,ai、bi、ti,表示从据点ai通过第i个栈道到bi耗时ti
Output
仅包含一个数,为需要添加的最少陷阱数。
Sample Input
3
1 2 1
1 3 3
Sample Output
2
Data Constraint
对于 5%的数据,1<=n<=100000,1<=ti<=200000
对于 100%的数据,1<=n<=500000,0<ti<=1000000
思路
题目要求的是最少,所以我们求最少。
回归正题。如果在公共的路上放一个陷阱,那么效果就会更好。也就是说我们要尽量在深度小的地方多放。
这里的话我们可以用
d
f
s
dfs
dfs处理一下。(这里没讲的太详细,留给大家自行思考吧
Code
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define N 500005
using namespace std;
int cnt,head[N],next[N],to[N],dis[N],n;
long long maxtime=-1;
long long mintime[N];
long long ans;
bool bz[N];
void add(int u,int v,int ti) {
next[++cnt]=head[u];
head[u]=cnt;
to[cnt]=v;
dis[cnt]=ti;
}
void ready_first(int u,int from,long long ntime,int las) {
if(!bz[u]) maxtime=max(maxtime,ntime);
for(int i=head[u];i;i=next[i]) {
int v=to[i];
if(v==from) continue;
ready_first(v,u,ntime+dis[i],i);
}
}
void ready_second(int u,int from,int las,long long ntime) {
if(!bz[u])
mintime[las]=maxtime-ntime;
for(int i=head[u];i;i=next[i]) {
int v=to[i];
if(v==from) continue;
ready_second(v,u,i,ntime+dis[i]);
mintime[las]=min(mintime[las],mintime[i]);
}
}
void do_work(int u,int from,long long delet) {
for(int i=head[u];i;i=next[i]) {
int v=to[i];
if(v==from) continue;
if(mintime[i]) ans+=(mintime[i]-delet);
do_work(v,u,max(delet,mintime[i]));
}
}
int main() {
scanf("%d",&n);
for(int i=1;i<n;i++) {
int u,v,ti;
scanf("%d%d%d",&u,&v,&ti);
bz[u]=true;
add(u,v,ti);
mintime[i]=9999999999;
}
mintime[n]=9999999999;
ready_first(1,0,0,0);
ready_second(1,0,0,0);
do_work(1,0,0);
printf("%lld",ans);
}