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

【贪心+数量剖分LCA】UOJ150-运输计划

时间:2016-08-08 12:15:11      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:

【题目大意】

题目大意:给定一棵包含n个结点的树,树上的边权表示运输的时间。给定m条运输计划,这些运输计划同时开始执行。现在可以把任意一条边的权值变成0,问使得这m条运输全部结束的最短时间是多少? n, m <= 300,000

【思路】

m条运输全部结束的时间取决于最长的那条路径的长度 选择变成0的那条边(u, v),一定在最长路径上,所以枚举最长路径上的每一条边 所有包含(u, v)这条边的路径,长度都要减去w(u, v),因此不会超过最长路径减去w(u, v) 需要在所有不包含(u, v)的路径里,选择一条最长的路径

发现题目中有部分数据,这棵树是一条单链。 对于最长链上的边(i, i + 1),需要知道 所有终点在i (inclusive) 之前的链中最长的 所有起点在i + 1 (inclusive) 之后的链中最长的

如果不是一条链怎么办?

(u2, v2) ? (u2’, v2’),路径长度不变 将所有其他路径和最长路径求交

求一棵树上两条链(u1, v1), (u2, v2)的交 求出所有6个点对的LCA(最近公共祖先),并找出深度最大的两个LCA,记为LCA1, LCA2 如果LCA1 == LCA(u1, v1) 或者LCA1 == LCA(u2, v2),则这两条路径没有交。否则这两条链的交就是(LCA2, LCA2)

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int MAXN=300000+50;
  7 struct edge
  8 {
  9     int to,next,val;
 10 }e[MAXN<<1];
 11 int h[MAXN],tp;
 12 void ae(int u,int v,int w)
 13 {
 14     e[++tp].to=v;e[tp].next=h[u];e[tp].val=w;h[u]=tp;
 15 }
 16 int n,m;
 17 bool vis[N];
 18 int que[N],sum[N];
 19 int fa[N],siz[N],son[N],top[N],dep[N];
 20 struct Que
 21 {
 22     int u,v,w,lca;
 23     bool operator <(const Que &a)const{
 24         return w>a.w;
 25     }
 26 }q[N];
 27 void bfs(int u)
 28 {
 29     int f,t;
 30     vis[u]=1;
 31     que[f=t=1]=1;
 32     while(f<=t)
 33     {
 34         int u=que[f++];siz[u]=1;
 35         for(int v,i=h[u];i;i=e[i].next)
 36         if(!vis[v=e[i].to])
 37         {
 38             dep[v]=dep[u]+1;sum[v]=sum[u]+e[i].val;
 39             fa[v]=u;vis[v]=1;que[++t]=v;
 40         }
 41     }
 42     for(int i=n;i;i--) 
 43     {
 44         siz[fa[que[i]]]+=siz[que[i]];
 45         if(siz[que[i]]>siz[son[fa[que[i]]]]) son[fa[que[i]]]=que[i];
 46     }
 47 }
 48 void dfs2(int u,int f,int t)
 49 {
 50     top[u]=t;
 51     if(son[u]) dfs2(son[u],u,t);
 52     for(int i=h[u];i;i=e[i].next)
 53     if(e[i].to!=f&&e[i].to!=son[u]) dfs2(e[i].to,u,e[i].to);
 54 }
 55 int get_lca(int x,int y)
 56 {
 57     while(top[x]!=top[y])
 58     {
 59         if(dep[top[x]]<dep[top[y]]) swap(x,y);
 60         x=fa[top[x]];
 61     }
 62     return dep[x]<dep[y]?x:y;
 63 }
 64 int tot[N],num;
 65 void work(int x,int y){tot[x]+=y;}
 66 bool check(int x)
 67 {
 68     num=0;
 69     memset(tot,0,sizeof(tot));
 70     for(int i=1;i<=m&&q[i].w>x;i++)
 71     {
 72         num++;
 73         work(q[i].u,1);work(q[i].v,1);
 74         work(q[i].lca,-2);
 75     }
 76     int mx=0;
 77     for(int i=n;i;i--)
 78     {
 79         if(tot[que[i]]==num) mx=max(mx,sum[que[i]]-sum[fa[que[i]]]);
 80         tot[fa[que[i]]]+=tot[que[i]];
 81     }
 82     return q[1].w-mx<=x;
 83 }
 84 #define LEN 1<<16
 85 char getc()
 86 {
 87     char *S,*T,buf[LEN];
 88     if(S==T)
 89     {
 90         T=(S=buf)+fread(buf,1,LEN,stdin);
 91         if(S==T)
 92             return EOF;
 93     }
 94     return *S++;
 95 }
 96 int read()
 97 {
 98     static char ch;
 99     static int D;
100     while(!isdigit(ch=getc()));
101     for(D=ch-0;isdigit(ch=getc());)
102         D=D*10+ch-0;
103     return D;
104 }
105 int main()
106 {
107     cin>>n>>m;
108     for(int u,v,w,i=1;i<n;i++) 
109     {
110         u=read();v=read();w=read();
111         ae(u,v,w);ae(v,u,w);
112     }
113     bfs(1);
114     dfs2(1,0,1);
115     for(int i=1;i<=m;i++)
116     {
117         q[i].u=read();q[i].v=read();
118         q[i].lca=get_lca(q[i].u,q[i].v);
119         q[i].w=sum[q[i].u]+sum[q[i].v]-2*sum[q[i].lca];
120     }
121     sort(q+1,q+m+1);
122     int l=0,r=n*1000,mid,ans=0;
123     while(l<=r)
124     {
125         mid=(l+r)>>1;
126         if(check(mid)) ans=mid,r=mid-1;
127         else l=mid+1;
128     }
129     printf("%d\n",ans);
130 }

 

【贪心+数量剖分LCA】UOJ150-运输计划

标签:

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

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