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

题目背景

公元 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

说明

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

请注意常数因子带来的程序效率上的影响。

【分析】

  这题,像是很多解法哦。

  首先是,你是选大的那几条链删掉公共边,就是树链的交,然后维护一个最大值【可是我不会树链的交【如果没有交链直接break就好了

  

  我打的是二分版本。  

  先预处理每条路径的LCA,二分答案,如果某条路径的长度大于这个二分答案,那么意味着他里面一定要割掉一条边嘛,

  那么,把这样的路径记录下来(那个,是一个很妙的方法,在x,y上标记1,在lca上标记-2,子树的sum就是它的访问次数,我们判断的时候只需要dfs一遍,回溯累加就好了)

  我们只能选择涵盖所有不合法路径的边减掉,取他们之中的max当然是更好的,然后看看这个max能不能使路径合法。

  【为什么我打的nlogxx比别人的暴力还慢【捂脸= =

  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
",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

原文地址:https://www.cnblogs.com/Konjakmoyu/p/6066297.html