码迷,mamicode.com
首页 > 其他好文 > 详细

【树链剖分】UOJ150-Transportation Plan

时间:2016-10-14 06:53:17      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:

【题目大意】

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

 

【树链剖分】UOJ150-Transportation Plan

标签:

原文地址:http://www.cnblogs.com/iiyiyi/p/5958625.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!