cf827D Best Edge Weight (kruskal+倍增lca+并查集)

先用kruskal处理出一个最小生成树

对于非树边,倍增找出两端点间的最大边权-1就是答案

对于树边,如果它能被替代,就要有一条非树边,两端点在树上的路径覆盖了这条树边,而且边权不大于这条树边

这里可以树剖来做,但是不想用..

如果先把非树边从小到大排序然后去覆盖树边,那么一条树边只需要被覆盖一次

所以可以用一个并查集来把父子边被覆盖的点合到一起,在合并之前记下来这次覆盖的边权,下次再覆盖的时候直接跳过去就可以

  1 #include<bits/stdc++.h>
  2 #define pa pair<int,int>
  3 #define CLR(a,x) memset(a,x,sizeof(a))
  4 using namespace std;
  5 typedef long long ll;
  6 const int maxn=2e5+10,inf=1e9+1;
  7 
  8 inline ll rd(){
  9     ll x=0;char c=getchar();int neg=1;
 10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
 11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
 12     return x*neg;
 13 }
 14 
 15 struct Edge{
 16     int a,b,l,ne;
 17     bool used;
 18 }eg[maxn],eg2[maxn*2];
 19 int egh[maxn],ect;
 20 int N,M,fa[maxn][20],bf[maxn],bm[maxn],ma[maxn][20],dep[maxn];
 21 int ans[maxn];
 22 
 23 inline int getf(int x){return bf[x]==x?x:bf[x]=getf(bf[x]);}
 24 inline bool cmp(Edge a,Edge b){return a.l<b.l;}
 25 inline void adeg(int a,int b,int c){
 26     eg2[++ect].b=b;eg2[ect].ne=egh[a];
 27     eg2[ect].l=c,egh[a]=ect;
 28 }
 29 
 30 void dfs(int x){
 31     // printf("!!%d %d %d
",x,fa[x][0],ma[x][0]);
 32     for(int i=0;fa[x][i]&&fa[fa[x][i]];i++)
 33         fa[x][i+1]=fa[fa[x][i]][i],ma[x][i+1]=max(ma[x][i],ma[fa[x][i]][i]);
 34     for(int i=egh[x];i;i=eg2[i].ne){
 35         int b=eg2[i].b;
 36         if(b==fa[x][0]) continue;
 37         ma[b][0]=eg2[i].l;
 38         fa[b][0]=x;dep[b]=dep[x]+1;
 39         dfs(b);
 40     }
 41 }
 42 
 43 int lca(int x,int y){
 44     if(dep[x]<dep[y]) swap(x,y);
 45     int re=0;
 46     for(int i=log2(dep[x]-dep[y]);i>=0&&dep[x]!=dep[y];i--){
 47         if(fa[x][i]&&dep[fa[x][i]]>=dep[y])
 48             re=max(re,ma[x][i]),x=fa[x][i];
 49     }
 50     if(x==y) return re;
 51     for(int i=log2(dep[x]);i>=0;i--){
 52         if(fa[x][i]!=fa[y][i])
 53             re=max(re,max(ma[x][i],ma[y][i])),x=fa[x][i],y=fa[y][i];
 54     }
 55     return max(re,max(ma[x][0],ma[y][0]));
 56 }
 57 
 58 int main(){
 59     //freopen("","r",stdin);
 60     int i,j,k;
 61     N=rd(),M=rd();
 62     for(i=1;i<=M;i++){
 63         eg[i].a=rd(),eg[i].b=rd(),eg[i].l=rd();
 64         eg[i].ne=i;
 65     }
 66     sort(eg+1,eg+M+1,cmp);
 67     for(i=1;i<=N;i++) bf[i]=i;
 68     for(i=1,j=0;i<=M&&j<N-1;i++){
 69         int a=getf(eg[i].a),b=getf(eg[i].b);
 70         if(a!=b){
 71             bf[a]=b;
 72             adeg(eg[i].a,eg[i].b,eg[i].l);
 73             adeg(eg[i].b,eg[i].a,eg[i].l);
 74             eg[i].l=inf;eg[i].used=1;
 75             j++;
 76         }
 77     }
 78     dep[1]=1;dfs(1);
 79     sort(eg+1,eg+M+1,cmp);
 80     for(i=1;i<=N;i++) bf[i]=i,bm[i]=inf;
 81     for(i=1;i<=M;i++){
 82         if(eg[i].used) continue;
 83         int a=getf(eg[i].a),b=getf(eg[i].b);
 84         while(a!=b){
 85             if(dep[a]<dep[b]) swap(a,b);
 86             int bb=getf(fa[a][0]);
 87             bf[a]=bb,bm[a]=eg[i].l;
 88             a=bb;
 89         }
 90     }
 91     for(i=1;i<=M;i++){
 92         if(eg[i].used){
 93             int a=eg[i].a,b=eg[i].b;
 94             if(dep[a]<dep[b]) swap(a,b);
 95             // a=getf(a),b=getf(b);
 96             if(bm[a]<inf) ans[eg[i].ne]=bm[a]-1;
 97             else ans[eg[i].ne]=-1;
 98         }else{
 99             ans[eg[i].ne]=lca(eg[i].a,eg[i].b)-1;
100         }
101     }
102     for(i=1;i<=M;i++)
103         printf("%d ",ans[i]);
104     return 0;
105 }
原文地址:https://www.cnblogs.com/Ressed/p/9811368.html