LOJ2425 NOIP2015 运输计划 【二分+LCA+树上差分】*
LOJ2425 NOIP2015 运输计划
题意:给你一颗树,可以将任意一条边的权值变成0,然后求m条路径的长度的最小值
思路:
先二分最后的距离ans,然后我们把路程大于ans的所有路径拿出来
然后把这些路径的交求出来,用树上差分的方法
然后对这个交(用点集转化成边集,就是每个点的上一条边)取一个最大值
然后判断这些边减去这个最大值之后会不会小于等于ans
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define fu(a,b,c) for(int a=b;a<=c;++a) 4 #define fd(a,b,c) for(int a=b;a>=c;--a) 5 int read(){ 6 int ans=0,w=1;char c=getchar(); 7 while(!isdigit(c)&&c!='-')c=getchar(); 8 if(c=='-')w=-1,c=getchar(); 9 while(isdigit(c))ans=(ans<<1)+(ans<<3)+c-'0',c=getchar(); 10 return ans*w; 11 } 12 const int N=3e5+10; 13 struct Edge{int v,w,next;}E[N<<1]; 14 int head[N],tot=0; 15 int n,m,l=0,r=0; 16 int cost[N],fro[N],to[N],lca[N]; 17 int dis[N],dep[N],cnt[N],pre[N]; 18 int fa[N][20],Log2[N]; 19 void add(int u,int v,int w){E[++tot]=(Edge){v,w,head[u]};head[u]=tot;} 20 void dfs(int u){ 21 dep[u]=dep[fa[u][0]]+1; 22 fu(i,1,Log2[dep[u]])fa[u][i]=fa[fa[u][i-1]][i-1]; 23 for(int i=head[u];i;i=E[i].next){ 24 int v=E[i].v; 25 if(v==fa[u][0])continue; 26 pre[v]=i; 27 fa[v][0]=u; 28 dis[v]=dis[u]+E[i].w; 29 dfs(v); 30 } 31 } 32 void redfs(int u){ 33 for(int i=head[u];i;i=E[i].next){ 34 int v=E[i].v; 35 if(v==fa[u][0])continue; 36 redfs(v); 37 cnt[u]+=cnt[v]; 38 } 39 } 40 int LCA(int x,int y){ 41 if(dep[x]<dep[y])swap(x,y); 42 int t=dep[x]-dep[y]; 43 fu(i,0,Log2[t])if(t&(1<<i))x=fa[x][i]; 44 if(x==y)return x; 45 int k=Log2[dep[x]]; 46 while(fa[x][0]!=fa[y][0]){ 47 if(fa[x][k]!=fa[y][k]){ 48 x=fa[x][k]; 49 y=fa[y][k]; 50 } 51 k--; 52 } 53 return fa[x][0]; 54 } 55 bool check(int vl){ 56 int siz=0; 57 fu(i,1,n)cnt[i]=0; 58 fu(i,1,m){ 59 if(cost[i]<=vl)continue; 60 siz++; 61 cnt[fro[i]]++; 62 cnt[to[i]]++; 63 cnt[lca[i]]-=2; 64 } 65 redfs(1); 66 int maxv=0; 67 fu(i,1,n){ 68 if(cnt[i]!=siz)continue; 69 maxv=max(maxv,E[pre[i]].w); 70 } 71 fu(i,1,m)if(cost[i]-maxv>vl)return 0; 72 return 1; 73 } 74 int main(){ 75 n=read();m=read(); 76 Log2[1]=0;fu(i,2,n)Log2[i]=Log2[i>>1]+1; 77 fu(i,1,n-1){ 78 int u=read(),v=read(),w=read(); 79 add(u,v,w); 80 add(v,u,w); 81 } 82 dfs(1); 83 fu(i,1,m){ 84 fro[i]=read(),to[i]=read(); 85 lca[i]=LCA(fro[i],to[i]); 86 cost[i]=dis[fro[i]]+dis[to[i]]-(dis[lca[i]]<<1); 87 r=max(r,cost[i]); 88 } 89 int ans; 90 while(l<=r){ 91 int mid=(l+r*2)/3; 92 if(check(mid))r=mid-1,ans=mid; 93 else l=mid+1; 94 } 95 printf("%d",ans); 96 return 0; 97 }