您的位置:首页 > 其它

【NOIP 2015 DAY2 T3】 运输计划 (树链剖分-LCA)

2016-11-15 16:36 429 查看

题目背景

公元 2044 年,人类进入了宇宙纪元。

题目描述

L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球。

小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物

流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道 是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之 间不会产生任何干扰。

为了鼓励科技创新,L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小 P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后, 这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的 物流公司的阶段性工作就完成了。

如果小 P 可以自由选择将哪一条航道改造成虫洞,试求出小 P 的物流公司完成阶段 性工作所需要的最短时间是多少?

输入输出格式

输入格式:

输入文件名为 transport.in。

第一行包括两个正整数 n、m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号。

接下来 n-1 行描述航道的建设情况,其中第 i 行包含三个整数 ai, bi 和 ti,表示第

i 条双向航道修建在 ai 与 bi 两个星球之间,任意飞船驶过它所花费的时间为 ti。

接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 uj 和 vj,表示第 j个 运输计划是从 uj 号星球飞往 vj 号星球。

输出格式:

输出 共1行,包含1个整数,表示小P的物流公司完成阶段性工作所需要的最短时间。

输入输出样例

输入样例#1:

6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5


输出样例#1:

11


说明

所有测试数据的范围和特点如下表所示

1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 #include<algorithm>
6 #include<queue>
7 #include<cmath>
8 using namespace std;
9 #define Maxn 300010
10 #define LL long long
11
12 struct node
13 {
14     int x,y,c,next;
15 }t[Maxn*2];int len;
16
17 int n,m;
18
19 int first[Maxn];
20 int ax[Maxn],ay[Maxn],lca[Maxn];
21 LL h[Maxn],ln[Maxn];
22
23 void ins(int x,int y,int c)
24 {
25     t[++len].x=x;t[len].y=y;t[len].c=c;
26     t[len].next=first[x];first[x]=len;
27 }
28
29 LL mymax(LL x,LL y) {return x>y?x:y;}
30
31 int dep[Maxn],dfn[Maxn],sm[Maxn],son[Maxn];
32 int fa[Maxn],w[Maxn];
33 void dfs1(int x,int f)
34 {
35     dep[x]=dep[f]+1;sm[x]=1;son[x]=0;
36     fa[x]=f;
37     for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
38     {
39         int y=t[i].y;
40         w[y]=t[i].c;
41         dfs1(y,x);
42         sm[x]+=sm[y];
43         if(sm[y]>sm[son[x]]) son[x]=y;
44     }
45 }
46
47 int tp[Maxn],cnt=0;
48 void dfs2(int x,int tpp)
49 {
50     dfn[x]=++cnt;h[cnt]=h[cnt-1]+w[x];
51     tp[x]=tpp;
52     if(son[x]) dfs2(son[x],tpp);
53     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x]&&t[i].y!=son[x])
54     {
55         int y=t[i].y;
56         dfs2(y,y);
57     }
58 }
59
60 void ffind(int id,int x,int y)
61 {
62     int tt;
63     while(tp[x]!=tp[y])
64     {
65         if(dep[tp[x]]<dep[tp[y]]) tt=x,x=y,y=tt;
66         ln[id]+=h[dfn[x]]-h[dfn[tp[x]]-1];
67         x=fa[tp[x]];
68     }
69     if(dep[x]<dep[y]) tt=x,x=y,y=tt;
70     ln[id]+=h[dfn[x]]-h[dfn[y]];
71     lca[id]=y;
72 }
73
74 int tot[Maxn];
75
76 int les(int x,int tt)
77 {
78     int ans=-1;
79     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x])
80     {
81         int y=t[i].y;
82         int now=les(y,tt);
83         tot[x]+=tot[y];
84         if(now!=-1) ans=mymax(ans,now);
85     }
86     if(tot[x]==tt) ans=mymax(ans,w[x]);
87     return ans;
88 }
89
90 bool check(LL mid)
91 {
92     memset(tot,0,sizeof(tot));
93     LL mx=0;int tt=0;
94     for(int i=1;i<=m;i++) if(ln[i]>mid)
95     {
96             tot[ax[i]]++;tot[ay[i]]++;
97             tot[lca[i]]-=2;
98         mx=mymax(mx,ln[i]);
99         tt++;
100     }
101     int now=les(1,tt);
102     if(now==-1||mx-now>mid) return 0;
103     return 1;
104 }
105
106 void get_ans(LL l,LL r)
107 {
108     while(l<r)
109     {
110         LL mid=(l+r)/2;
111         if(check(mid)) r=mid;
112         else l=mid+1;
113     }
114     printf("%lld\n",l);
115 }
116
117 int main()
118 {
119     LL mx=0;
120     scanf("%d%d",&n,&m);
121     len=0;
122     memset(first,0,sizeof(first));
123     for(int i=1;i<n;i++)
124     {
125         int x,y,c;
126         scanf("%d%d%d",&x,&y,&c);
127         ins(x,y,c);ins(y,x,c);
128     }
129     dep[0]=0;
130     dfs1(1,0);h[0]=0;
131     dfs2(1,1);
132     for(int i=1;i<=m;i++)
133     {
134         scanf("%d%d",&ax[i],&ay[i]);
135         ffind(i,ax[i],ay[i]);
136         mx=mymax(mx,ln[i]);
137     }
138     get_ans(0,mx);
139     return 0;
140 }


View Code

2016-11-15 16:41:22
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: