LOJ2425 NOIP2015 运输计划 【二分+LCA+树上差分】*

LOJ2425 NOIP2015 运输计划


LINK


题意:给你一颗树,可以将任意一条边的权值变成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 }
原文地址:https://www.cnblogs.com/dream-maker-yk/p/9676255.html