Codeforces827D. Best Edge Weight

$n leq 2e5,m leq 2e5$的有边权图,对每条边问:不改其他边的情况下这条边最多能是多少使得他一定在所有最小生成树上,如果无穷大输出-1.

典型题+耗时题,CF上的绝望时刻。。打VP时前三题花时间太多,导致这题看完题只剩20min,代码还得再敲稳点。

好进入正题,瞎造一棵最小生成树先然后分树上边和树外边回答,树外边$(x,y)$要替代树链$x-y$的某条边,必须比树链上最大的那条边要小1,是一个树链求$Max$,可以st表搞定;树上的边要刚好不被树外边替代,那应该刚好小于能替代它的最小的树外边,需要拿树外边$(x,y)$的权值来对链$x-y$上的边取个$Min$,对应区间取$Min$和离线查询,可以用排序+并查集(反正求最小生成树的时候边已经排序了)。

原来排序+并查集这种操作叫$the smaller-to-larger optimization$啊!

  1 //#include<iostream>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 //#include<queue>
  6 //#include<math.h>
  7 //#include<time.h>
  8 //#include<complex>
  9 #include<algorithm>
 10 using namespace std;
 11 
 12 int n,m;
 13 #define maxn 200011
 14 #define maxm 400011
 15 struct Edge{int from,to,next,v;}ee[maxm],edge[maxn<<1]; int first[maxn],le=2;
 16 void in(int x,int y,int v) {Edge &e=edge[le]; e.from=x; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;}
 17 void insert(int x,int y,int v) {in(x,y,v); in(y,x,v);}
 18 
 19 bool cmpee(const Edge &a,const Edge &b) {return a.v<b.v;}
 20 int ufs[maxn];
 21 int find(int x) {return x==ufs[x]?x:(ufs[x]=find(ufs[x]));}
 22 
 23 int fa[maxn][20],dep[maxn],st[maxn][20];
 24 void dfs(int x,int f)
 25 {
 26     fa[x][0]=f; dep[x]=dep[f]+1;
 27     for (int i=first[x];i;i=edge[i].next)
 28     {
 29         Edge &e=edge[i]; if (e.to==f) continue;
 30         st[e.to][0]=e.v; dfs(e.to,x);
 31     }
 32 }
 33 int Log[maxn];
 34 void makefa()
 35 {
 36     Log[0]=-1; for (int i=1;i<=n;i++) Log[i]=Log[i>>1]+1;
 37     for (int j=1;j<=18;j++)
 38         for (int i=1;i<=n;i++)
 39         {
 40             fa[i][j]=fa[fa[i][j-1]][j-1];
 41             st[i][j]=max(st[i][j-1],st[fa[i][j-1]][j-1]);
 42         }
 43 }
 44 
 45 int gg;
 46 int glca(int x,int y)
 47 {
 48     gg=0;
 49     if (dep[x]<dep[y]) {int t=x;x=y;y=t;}
 50     for (int j=18;j>=0;j--) if (dep[fa[x][j]]>=dep[y]) gg=max(st[x][j],gg),x=fa[x][j];
 51     if (x==y) return x;
 52     for (int j=18;j>=0;j--) if (fa[x][j]!=fa[y][j]) gg=max(gg,max(st[x][j],st[y][j])),x=fa[x][j],y=fa[y][j];
 53     gg=max(gg,max(st[x][0],st[y][0]));
 54     return fa[x][0];
 55 }
 56 
 57 int val[maxn];
 58 void modify(int x,int y,int v)
 59 {
 60     x=find(x);
 61     while (dep[x]>dep[y])
 62     {
 63         val[x]=v;
 64         x=ufs[x]=find(fa[x][0]);
 65     }
 66 }
 67 
 68 bool vis[maxm]; int ans[maxm];
 69 int main()
 70 {
 71     scanf("%d%d",&n,&m);
 72     for (int i=1;i<=m;i++) scanf("%d%d%d",&ee[i].from,&ee[i].to,&ee[i].v),ee[i].next=i;
 73     sort(ee+1,ee+1+m,cmpee);
 74     
 75     for (int i=1;i<=n;i++) ufs[i]=i;
 76     for (int i=1,j=1;i<=m && j<n;i++)
 77     {
 78         int x=find(ee[i].from),y=find(ee[i].to);
 79         if (x==y) continue;
 80         ufs[x]=y; insert(ee[i].from,ee[i].to,ee[i].v); vis[i]=1; j++;
 81     }
 82     dfs(1,0); makefa();
 83     
 84     for (int i=1;i<=n;i++) ufs[i]=i;
 85     for (int i=1;i<=n;i++) val[i]=0x3f3f3f3f;
 86     for (int i=1;i<=m;i++) if (!vis[i])
 87     {
 88         int x=ee[i].from,y=ee[i].to,l=glca(x,y);
 89         ans[ee[i].next]=gg-1;
 90         modify(x,l,ee[i].v); modify(y,l,ee[i].v);
 91     }
 92     for (int i=1;i<=m;i++) if (vis[i])
 93     {
 94         int x=ee[i].from,y=ee[i].to;
 95         if (dep[x]<dep[y]) x=y;
 96         ans[ee[i].next]=val[x]-1;
 97     }
 98     for (int i=1;i<=m;i++) printf("%d ",ans[i]==0x3f3f3f3f-1?-1:ans[i]);
 99     return 0;
100 }
View Code
原文地址:https://www.cnblogs.com/Blue233333/p/8530937.html