标签:
【题目大意】
题目大意:给定一棵包含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 }
标签:
原文地址:http://www.cnblogs.com/iiyiyi/p/5748374.html