公元 2044 年,人类进入了宇宙纪元。L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球。小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之间不会产生任何干扰。为了鼓励科技创新, L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后,这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的物流公司的阶段性工作就完成了。如果小 P 可以自由选择将哪一条航道改造成虫洞, 试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?
【思路】
一个优化:容易知道选择的航道一定在最长航道上。求LCA的时候直接可以处理出长度,不需要用线段树……
1 #include<bits/stdc++> 2 using namespace std; 3 const int MAXN=300000+50; 4 const int INF=0x7fffffff; 5 vector<int> E[MAXN]; 6 int n,m,dep[MAXN],fa[MAXN],size[MAXN],son[MAXN],top[MAXN]; 7 int sum[MAXN],que[MAXN]; 8 int maxlen,maxpos; 9 10 void dfs1(int u,int father,int depth) 11 { 12 fa[u]=father; 13 dep[u]=depth; 14 size[u]=1; 15 son[u]=-1; 16 for (int i=0;i<E[u].size();i++) 17 { 18 int v=E[u][i]; 19 if (v==fa) continue; 20 dfs(v,u,depth+1); 21 if (son[u]==-1 || size[v]>size[son[u]]) son[u]=v; 22 } 23 } 24 25 void dfs2(int u,int utop) 26 { 27 top[u]=utop;s 28 if (son[u]!=-1) dfs2(son[u],utop); 29 for (int i=0;i<E[u].size();i++) 30 { 31 int v=E[u][i]; 32 if (v==son[u] || v==fa[u]) continue; 33 dfs2(v,v); 34 } 35 } 36 37 int lca(int x,y) 38 { 39 int ret=0; 40 while (top[x]!=top[y]) 41 { 42 if (dep[top[u]]<dep[top[v]]) swap(u,v); 43 u=fa[top[u]]; 44 } 45 return dep[u]<dep[v]?u:v; 46 } 47 48 void dfs(int u) 49 { 50 for (int i=0;i<E[u].size();i++) 51 { 52 int v=E[u][i]; 53 if (v==fa[u]) continue; 54 dfs(v); 55 sum[u]+=sum[v]; 56 } 57 } 58 59 void check(int x) 60 { 61 int d=0,p=0; 62 //d记录当前x和最长的路径长的最大差值 63 //p记录总共有几条边要比x长 64 if (maxlen<=x) return 1; 65 memset(sum,0,sizeof(sum)); 66 for (int i=1;i<=m;i++) 67 if (task[i].d>x) 68 { 69 sum[task[i].u]++; 70 sum[task[i].v]++; 71 sum[task[i].g]-=2; 72 p++; 73 d=max(d,task[i].d-x); 74 } 75 dfs(task[maxdis].g); 76 for (int i=1;i<=cnt;i++) 77 { 78 if (sum[task[i].u]==p && sum[task[i].v]==p && task[i].d>d) 79 } 80 } 81 82 void init() 83 { 84 scanf("%d%d",&n,&m); 85 for (int i=1;i<n;i++) 86 { 87 int u,v,w; 88 scanf("%d%d%d",&u,&v,&w); 89 E[u].push_back(v); 90 } 91 dfs1(1,0,1); 92 dfs2(1,1); 93 maxlen=0; 94 for (int i=1;i<=m;i++) 95 { 96 scanf("%d%d",&task[i].u,task[i].v); 97 task[i].g=lca(task[i].u,task[i].v); 98 task[i].d=dep[task[i].u]+dep[task[i].v]-2*dep[task[i].g]+1; 99 if (task[i].d>maxlen) 100 { 101 maxlen=task[i].d; 102 maxdis=i; 103 } 104 } 105 } 106 107 void bi() 108 { 109 int lb=0,ub=INF; 110 while (lb<rb-1) 111 { 112 int mid=(l+r)>>1; 113 if (check(mid)) ub=mid; 114 else lb=mid; 115 } 116 return ub; 117 } 118 119 int main() 120 { 121 init(); 122 bi(); 123 return 0; 124 }