4326: NOIP2015 运输计划
Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1091 Solved: 696
[ Submit][ Status][ Discuss]
Description
公元 2044 年,人类进入了宇宙纪元。L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球。小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之间不会产生任何干扰。为了鼓励科技创新, L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后,这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的物流公司的阶段性工作就完成了。如果小 P 可以自由选择将哪一条航道改造成虫洞, 试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?
Input
第一行包括两个正整数 n,m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号。接下来 n−1 行描述航道的建设情况,其中第 i 行包含三个整数 ai,bi 和 ti,表示第 i 条双向航道修建在 ai 与 bi 两个星球之间,任意飞船驶过它所花费的时间为 ti。数据保证 1≤ai,bi≤n 且 0≤ti≤1000。接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 uj 和 vj,表示第 j 个运输计划是从 uj 号星球飞往 vj号星球。数据保证 1≤ui,vi≤n
Output
输出文件只包含一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。
Sample Input
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5
Sample Output
HINT
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxx = 300000 + 100;
const int maxm = 300000 + 50;
int head[maxx],next[maxx<<1],to[maxx<<1],val[maxx<<1];
int grand[maxx][20+2],depth[maxx],tmp[maxx],dis[maxx],prev[maxx],kth[maxx];
bool done[maxx];
int n,m,root,x,y,z,num,T,size,tot,ans;
template<class T> T chkmax(const T &a,const T &b) {return a>b? a : b;}
struct Que{
int s;
int t;
int Dis;
int lca;
}Q[maxm];
inline int read(){
int x=0,f=1;char c=getchar();
while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
return x*f;
}
void Add(int x,int y,int z){
next[++num] = head[x];
to[num] = y;
val[num] = z;
head[x] = num;
}
void Dfs(int x){
kth[++size] = x;
done[x] = true;
for(int i=1;i<=20;i++){
if(depth[x] < (1<<i)) break;
grand[x][i] = grand[grand[x][i-1]][i-1];
}
for(int i=head[x];i;i=next[i]){
int now = to[i];
if(done[now]) continue;
grand[now][0] = x;
depth[now] = depth[x] + 1;
dis[now] = dis[x] + val[i];
prev[now] = val[i];
Dfs(now);
}
}
int Lca(int x,int y){
if(depth[x] > depth[y]) x^=y^=x^=y;
int d = depth[y] - depth[x];
for(int i=0;i<=20;i++)
if((1<<i) & d) y = grand[y][i];
for(int i=20;i>=0;i--){
if(grand[x][i] != grand[y][i])
x = grand[x][i],y = grand[y][i];
}
return x == y? x : grand[x][0];
}
bool check(int x){
int cnt=0,dist=0;
memset(tmp,0,sizeof(tmp));
for(int i=1;i<=m;i++){
if(Q[i].Dis > x){
tmp[Q[i].s]++;tmp[Q[i].t]++;
tmp[Q[i].lca] -= 2;
dist=chkmax(dist,Q[i].Dis-x);
cnt++;
}
}
if(!cnt) return true;
for(int i=n;i>1;i--)
tmp[grand[kth[i]][0]] += tmp[kth[i]];
for(int i=2;i<=n;i++)
if(tmp[i]==cnt && prev[i]>=dist)
return true;
return false;
}
int work(){
int l=0,r=tot,Ans,mid;
while(l<=r){
mid=(l+r)>>1;
if(check(mid))
Ans=mid,r=mid-1;
else l=mid+1;
}
return Ans;
}
int main(){
n = read();m = read();
for(int i=1;i<n;i++){
x=read();y=read();z=read();
Add(x,y,z);Add(y,x,z);
tot += z;
}
Dfs(1);
for(int i=1;i<=m;i++){
x=read();y=read();
Q[i].s=x;Q[i].t=y;
Q[i].lca=Lca(x,y);
Q[i].Dis=dis[x]+dis[y]-((dis[Lca(x,y)])<<1);
}
printf("%d\n",work());
return 0;
}