[cf1184E]Daleks' Invasion

先求出任意一棵最小生成树,然后对边分类讨论
1.非树边,答案即最小生成树的环上的最长边
2.树边,反过来考虑,相当于对于每一个点对那条路经打上标记,取min
对于1直接用倍增维护即可,对于2可以用树链剖分/差分+启发式合并但都需要两个log,所以有一种很神奇的做法
考虑从小到大枚举非树边,然后暴力修改,容易发现修改过的边就不用修改了,因此复杂度是o(m),问题是如何快速找到没有被修改过的边,可以使用并查集将修改过的边缩起来然后快速往上爬即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 #define mid (l+r>>1)
 5 struct ji{
 6     int x,y,z,id;
 7 }e[N*10];
 8 struct ji2{
 9     int nex,to,len,id;
10 }edge[N<<1];
11 int E,n,m,x,y,head[N],sh[N],ff[N],up[N],vis[N*10],ans[N*10],f[N][21],mx[N][21];
12 bool cmp(ji x,ji y){
13     return x.z<y.z;
14 }
15 int find(int k){
16     if (k==ff[k])return k;
17     return ff[k]=find(ff[k]);
18 }
19 void add(int x,int y,int z,int id){
20     edge[E].nex=head[x];
21     edge[E].to=y;
22     edge[E].len=z;
23     edge[E].id=id;
24     head[x]=E++;
25 }
26 void dfs(int k,int fa,int id,int s){
27     sh[k]=s;
28     up[k]=id;
29     f[k][0]=fa;
30     for(int i=1;i<=20;i++){
31         f[k][i]=f[f[k][i-1]][i-1];
32         mx[k][i]=max(mx[k][i-1],mx[f[k][i-1]][i-1]);
33     }
34     for(int i=head[k];i!=-1;i=edge[i].nex)
35         if (edge[i].to!=fa){
36             mx[edge[i].to][0]=edge[i].len;
37             dfs(edge[i].to,k,edge[i].id,s+1);
38         }
39 }
40 pair<int,int> lca(int x,int y){
41     if (sh[x]<sh[y])swap(x,y);
42     int ans=0;
43     for(int i=20;i>=0;i--)
44         if (sh[f[x][i]]>=sh[y]){
45             ans=max(ans,mx[x][i]);
46             x=f[x][i];
47         }
48     if (x==y)return make_pair(x,ans);
49     for(int i=20;i>=0;i--)
50         if (f[x][i]!=f[y][i]){
51             ans=max(ans,max(mx[x][i],mx[y][i]));
52             x=f[x][i];
53             y=f[y][i];
54         }
55     return make_pair(f[x][0],max(ans,max(mx[x][0],mx[y][0])));
56 }
57 int main(){
58     scanf("%d%d",&n,&m);
59     for(int i=1;i<=m;i++){
60         scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
61         e[i].id=i;
62     }
63     sort(e+1,e+m+1,cmp);
64     memset(head,-1,sizeof(head));
65     for(int i=1;i<=n;i++)ff[i]=i;
66     for(int i=1;i<=m;i++){
67         x=find(e[i].x);
68         y=find(e[i].y);
69         if (x!=y){
70             ff[x]=y;
71             add(e[i].x,e[i].y,e[i].z,e[i].id);
72             add(e[i].y,e[i].x,e[i].z,e[i].id);
73             vis[i]=1;
74         }
75     }
76     dfs(1,0,0,0);
77     for(int i=1;i<=m;i++)ans[i]=1000000000;
78     for(int i=1;i<=n;i++)ff[i]=i;
79     for(int i=1;i<=m;i++)
80         if (!vis[i]){
81             x=lca(e[i].x,e[i].y).first;
82             ans[e[i].id]=lca(e[i].x,e[i].y).second;
83             while (find(e[i].x)!=find(x)){
84                 e[i].x=find(e[i].x);
85                 ans[up[e[i].x]]=e[i].z;
86                 if (find(e[i].x)!=find(f[e[i].x][0]))ff[find(e[i].x)]=find(f[e[i].x][0]);
87             }
88             while (find(e[i].y)!=find(x)){
89                 e[i].y=find(e[i].y);
90                 ans[up[e[i].y]]=e[i].z;
91                 if (find(e[i].y)!=find(f[e[i].y][0]))ff[find(e[i].y)]=find(f[e[i].y][0]);
92             }
93         }
94     for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
95 }
View Code

猜你喜欢

转载自www.cnblogs.com/PYWBKTDA/p/11842540.html