MST(最小生成树+倍增)
Posted harrypotter-fan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MST(最小生成树+倍增)相关的知识,希望对你有一定的参考价值。
题目描述:
给定一个n个点m条边的连通图,保证没有自环和重边。对于每条边求出,在其他边权值不变的情况下,它能取的最大权值,使得这条边在连通图的所有最小生成树上。假如最大权值为无限大,则输出-1。
题解:
先求出图的一棵最小生成树:
对于不在树上的边(x,y), 它的权值只要小于树上x到y路径中一条边就可以代替这条边。
对于在树上的边(x,y),可以先预处理出所有两端在x到y路径上的不在树上的边的最小值。它的权值一定要小于最小值。
路径max和min都可以用倍增求。
时间复杂度O(nlogn)
#include<bits/stdc++.h> using namespace std; const int N=2e5+5; inline int read() int x=0,f=1; char ch=getchar(); while(!isdigit(ch))if(ch==‘-‘)f=-1;ch=getchar(); while(isdigit(ch))x=x*10+ch-‘0‘;ch=getchar(); return x*f; int n,m,cnt=0,head[N]; int vis[N],ans[N]; int fa[N],dep[N],id[N]; int f[N][20],maxn[N][20]; struct data int x,y,dis,id; a[N]; struct Edge int v,w,nxt,id; edge[N<<1]; void add_edge(int u,int v,int w,int id) edge[++cnt].v=v;edge[cnt].w=w;edge[cnt].id=id;edge[cnt].nxt=head[u];head[u]=cnt; int find(int x) if(fa[x]==x) return fa[x]; else return fa[x]=find(fa[x]); bool cmp(data a,data b) return a.dis<b.dis; void build() sort(a+1,a+m+1,cmp); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) int x=a[i].x; int y=a[i].y; if(find(x)!=find(y)) fa[find(x)]=find(y); vis[a[i].id]=1; add_edge(x,y,a[i].dis,a[i].id); add_edge(y,x,a[i].dis,a[i].id); void dfs(int u) for(int i=1;i<=18;i++) f[u][i]=f[f[u][i-1]][i-1]; maxn[u][i]=max(maxn[u][i-1],maxn[f[u][i-1]][i-1]); for(int i=head[u];i;i=edge[i].nxt) int v=edge[i].v; int w=edge[i].w; if(v==f[u][0]) continue; dep[v]=dep[u]+1; id[v]=edge[i].id; f[v][0]=u; maxn[v][0]=w; dfs(v); void solve(int x,int y,int dis) x=find(x); while(dep[x]>dep[y]) ans[id[x]]=min(ans[id[x]],dis-1); int k=find(f[x][0]); fa[x]=k; x=find(x); int get(int x,int y,int &lca) int ans=0; if(dep[x]<dep[y]) swap(x,y); for(int i=18;i>=0;i--) if(dep[f[x][i]]>=dep[y]) ans=max(ans,maxn[x][i]); x=f[x][i]; if(x==y) lca=x; return ans; for(int i=18;i>=0;i--) if(f[x][i]!=f[y][i]) ans=max(ans,maxn[x][i]); ans=max(ans,maxn[y][i]); x=f[x][i],y=f[y][i]; lca=f[x][0]; return max(ans,max(maxn[x][0],maxn[y][0])); int main() n=read();m=read(); for(int i=1;i<=m;i++) a[i].x=read();a[i].y=read();a[i].dis=read(); ans[i]=2e9; a[i].id=i; build();dfs(1); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) if(!vis[a[i].id]) int x=a[i].x,y=a[i].y,z; ans[a[i].id]=get(x,y,z)-1; solve(x,z,a[i].dis); solve(y,z,a[i].dis); for(int i=1;i<=m;i++) if(ans[i]==2e9) printf("-1 "); else printf("%d ",ans[i]);
以上是关于MST(最小生成树+倍增)的主要内容,如果未能解决你的问题,请参考以下文章
POJ 1679 The Unique MST:次小生成树倍增