萌新求调次小生成树
查看原帖
萌新求调次小生成树
92682
Eric_cai楼主2021/11/8 22:13
#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 100005
#define int long long
using namespace std;
struct Edge
{
	int u,v,w;
};
Edge a[maxn<<2];
bool cmp(Edge A,Edge B)
{
	return A.w<B.w;
}
struct Eric_cai
{
	int to,next,val;
};
Eric_cai EC[maxn<<3];
int head[maxn],cnt;
void add(int u,int v,int w)
{
	EC[++cnt].to=v;
	EC[cnt].next=head[u];
	EC[cnt].val=w;
	head[u]=cnt;
}
int fa[maxn][25],Max[maxn][25],Sec[maxn][25],vis[maxn];
int n,m,sz,f[maxn],Min,ans=1e18,dep[maxn];
int get_fa(int x)
{
	if(f[x]==x) return x;
	return f[x]=get_fa(f[x]);
}
inline void merge(int x,int y)
{
	f[get_fa(x)]=get_fa(y);
}
void Kruskal()
{
	for(int i=1;i<=n;i++) f[i]=i;
	for(int i=1;i<=sz;i++)
	{
		if(get_fa(a[i].u)!=get_fa(a[i].v))
		{
			Min+=a[i].w;
			merge(a[i].u,a[i].v);
			vis[i]=1;
			add(a[i].u,a[i].v,a[i].w);
			add(a[i].v,a[i].u,a[i].w);
		}
	}
}
void dfs(int now,int F,int w)
{
	fa[now][0]=F;
	Max[now][0]=w;
	dep[now]=dep[F]+1;
	for(int i=1;i<=20;i++)
	{
	    fa[now][i]=fa[fa[now][i-1]][i-1];
	    Max[now][i]=max(Max[now][i-1],Max[fa[now][i-1]][i-1]);
	    Sec[now][i]=max(Sec[now][i-1],Sec[fa[now][i-1]][i-1]);
	    if(Max[now][i-1]!=Max[fa[now][i-1]][i-1])
		    Sec[now][i]=max(Sec[now][i],min(Max[now][i-1],Max[fa[now][i-1]][i-1]));
	}
	for(int i=head[now];i!=0;i=EC[i].next)
		if(EC[i].to!=F) dfs(EC[i].to,now,EC[i].val);
}
inline void upd(int &u,int x,int w)
{
	if(Max[u][x]==w) ans=min(ans,w-Sec[u][x]);
	else ans=min(ans,w-Max[u][x]);
	u=fa[u][x];
}
void get_ans(int u,int v,int w)
{
	if(dep[u]<dep[v]) swap(u,v);
	for(int i=20;i>=0;i--)
	    if(dep[fa[u][i]]>=dep[v]) upd(u,i,w);
	if(u==v) return;
	for(int i=20;i>=0;i--)
	{
		if(fa[u][i]!=fa[v][i])
		{
			upd(u,i,w);
			upd(v,i,w);
		}
	}
	upd(u,0,w);
	upd(v,0,w);
}
signed main()
{
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=m;i++)
	{
		sz++;
		scanf("%lld%lld%lld",&a[sz].u,&a[sz].v,&a[sz].w);
		if(a[i].u==a[i].v) sz--;
	}
	sort(a+1,a+1+sz,cmp);
	Kruskal();
	dfs(1,0,0);
	for(int i=1;i<=sz;i++)
		if(vis[i]!=1) get_ans(a[i].u,a[i].v,a[i].w);
	printf("%lld\n",ans+Min);
	return 0;
}
2021/11/8 22:13
加载中...