其他分享
首页 > 其他分享> > CF609E Minimum spanning tree for each edge

CF609E Minimum spanning tree for each edge

作者:互联网

先求出最小生成树。

加入一条边后肯定会形成环,我们需要找环上的非添加边的最大边,断掉。

也就是说,对于 \((u,v)\),找出 MST 里 \(u,v\) 间最大边权。

典型的边权树剖。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e5+5;
int n,m;
struct edge{
	int u,v,w,id;
	bool isin;
	bool operator <(const edge &b)const{return w<b.w;}
}Edge[maxn];
int Fa[maxn];
int Find(int x){
	return Fa[x]==x?x:Fa[x]=Find(Fa[x]);
}
int res=0;

vector<int> e[maxn];
int dep[maxn],fa[maxn],sze[maxn],son[maxn],to[maxn],seg[maxn],rev[maxn];
int a[maxn];
int xds[maxn<<2];
#define ls (k<<1)
#define rs (k<<1|1)
#define mid (l+r>>1)
void pushup(int k){
	xds[k]=max(xds[ls],xds[rs]);
}
void build(int k,int l,int r){
	if(l==r){
		xds[k]=a[rev[l]];
		return ;
	}
	build(ls,l,mid);build(rs,mid+1,r);
	pushup(k);
}
int query(int k,int l,int r,int x,int y){
	if(x<=l&&r<=y)return xds[k];
	int res=0;
	if(x<=mid)res=max(res,query(ls,l,mid,x,y));
	if(mid<y)res=max(res,query(rs,mid+1,r,x,y));
	return res;
}

void dfs1(int u,int f){
	fa[u]=f,dep[u]=dep[f]+1,sze[u]=1;
	for(auto v:e[u]){
		if(v!=f){
			dfs1(v,u);
			sze[u]+=sze[v];
			if(sze[v]>sze[son[u]])son[u]=v;
		}
	}
}
void dfs2(int u,int t){
	seg[u]=++seg[0],rev[seg[0]]=u,to[u]=t;
	if(!son[u])return ;
	dfs2(son[u],t); 
	for(auto v:e[u]){
		if(v!=fa[u]&&v!=son[u])dfs2(v,v);
	}
}
int treequery(int x,int y){
	int res=-0x3f3f3f3f;
	while(to[x]!=to[y]){
		if(dep[to[x]]<dep[to[y]])swap(x,y);
		res=max(res,query(1,1,n,seg[to[x]],seg[x]));
		x=fa[to[x]];
	}
	if(dep[x]>dep[y])swap(x,y);
	res=max(res,query(1,1,n,seg[x]+1,seg[y]));
    return res;
}
int ans[maxn];
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)Fa[i]=i;
	for(int i=1;i<=m;i++)cin>>Edge[i].u>>Edge[i].v>>Edge[i].w,Edge[i].isin=0,Edge[i].id=i; 
	sort(Edge+1,Edge+m+1);
	for(int i=1;i<=m;i++){
		int u=Edge[i].u,v=Edge[i].v,w=Edge[i].w;
		if(Find(u)==Find(v))continue;
		Fa[Find(u)]=Find(v);
		e[u].push_back(v);
		Edge[i].isin=1;
		e[v].push_back(u);
		res+=w;
	}
	dfs1(1,0);
	dfs2(1,1);
	for(int i=1;i<=m;i++){
		if(Edge[i].isin){
			int u=Edge[i].u,v=Edge[i].v,w=Edge[i].w;
			if(dep[u]<dep[v])a[v]=w;
			else a[u]=w;
		}
	}
	build(1,1,n);
	for(int i=1;i<=m;i++){
		if(Edge[i].isin)ans[Edge[i].id]=res;//实际上珂以不要
		else{
			int u=Edge[i].u,v=Edge[i].v,w=Edge[i].w;
			ans[Edge[i].id]=res+w-treequery(u,v);
		}
	}
    for(int i=1;i<=m;i++)cout<<ans[i]<<endl;
	return 0;
}

标签:int,tree,CF609E,son,seg,Minimum,Edge,maxn,xds
来源: https://www.cnblogs.com/kkksc0100/p/no-using_shengchenghanshu.html