【刷题】洛谷 P4234 最小差值生成树

摘要:
本主题描述了如何在给定标签为从到的无向图的情况下,找到边权重最大值和最小值之间差值最小的生成树。数据保证至少存在一个生成树。输入和输出样本输入样本#1:461210131001490232024803440输出样本#1:20显示,对于30%的数据,97%的数据,100%的数据,问题解决方案LCT首先从最大边权重到最小边权重排序,然后,以简单的方式枚举每边,并将其权重作为生成树的最小值。什么是最好的答案。显然,如果我们确定下限,则上限必须是MST的最大值,下限为最小值。
题目描述

给定一个标号为从 (1)(n) 的、有 (m) 条边的无向图,求边权最大值与最小值的差值最小的生成树。

输入输出格式

输入格式:

第一行两个数 (n, m) ,表示图的点和边的数量。

第二行起 (m) 行,每行形如 (u_i, v_i, w_i)​ ,代表 (u_i)​ 到 (v_i)​ 间有一条长为 (w_i)​ 的无向边。

输出格式:

输出一行一个整数,代表你的答案。

数据保证存在至少一棵生成树。

输入输出样例

输入样例#1:

4 6

1 2 10

1 3 100

1 4 90

2 3 20

2 4 80

3 4 40

输出样例#1:

20

说明

对于 30% 的数据,满足 (1 leq n leq 100, 1 leq m leq 1000)

对于 97% 的数据,满足 (1 leq n leq 500, 1 leq m leq 100000)

对于 100% 的数据,满足 (1 leq n leq 50000, 1 leq m leq 200000, 1 leq w_i leq 10000)

题解

LCT

先从对边按边权大到小排序

然后,朴素地看,我们枚举每条边,以它的权值作为生成树的最小值,最优答案是多少。显然,如果我们确定了下界,那么上界一定是以下界为最小值的MST中的最大值。所以,枚举了最小值,那么对于它的最优答案就是所有边权大于这个最小值的边组成的图的MST中的边权的最大值减去枚举的这个最小值。

由于已经从大到小排好序了,那么就直接不断加边,用LCT维护MST就行了

那么对于每一次枚举,都要找一次整个MST的最大值,这个用LCT做不到,那就直接用一个数组存某条边是否在MST中,再用一个指针一直指向最前面的存在于MST中的边就行了

当然,边权从小到大排序也可做,过程是一样的

从小到大,维护最大生成树

从大到小,维护最小生成树

#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
const int MAXN=50000+10,MAXM=200000+10,inf=0x3f3f3f3f;
int n,m,fa[MAXN],in[MAXM],ip=1,ans=inf;
struct edge{
	int u,v,w;
	inline bool operator < (const edge &A) const {
		return w>A.w;
	};
};
edge side[MAXM];
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
struct LCT{
	int ch[MAXN+MAXM][2],fa[MAXN+MAXM],rev[MAXN+MAXM],Mx[MAXN+MAXM],id[MAXN+MAXM],stack[MAXN+MAXM],cnt,val[MAXN+MAXM];
	inline void init()
	{
		memset(ch,0,sizeof(ch));
		memset(fa,0,sizeof(fa));
		memset(Mx,0,sizeof(Mx));
		memset(id,0,sizeof(id));
		memset(val,0,sizeof(val));
		memset(rev,0,sizeof(rev));
	}
	inline bool nroot(int x)
	{
		return lc(fa[x])==x||rc(fa[x])==x;
	}
	inline void reverse(int x)
	{
		std::swap(lc(x),rc(x));
		rev[x]^=1;
	}
	inline void pushup(int x)
	{
		Mx[x]=val[x];id[x]=x;
		if(Mx[lc(x)]>Mx[x])Mx[x]=Mx[lc(x)],id[x]=id[lc(x)];
		if(Mx[rc(x)]>Mx[x])Mx[x]=Mx[rc(x)],id[x]=id[rc(x)];
	}
	inline void pushdown(int x)
	{
		if(rev[x])
		{
			if(lc(x))reverse(lc(x));
			if(rc(x))reverse(rc(x));
			rev[x]=0;
		}
	}
	inline void rotate(int x)
	{
		int f=fa[x],p=fa[f],c=(rc(f)==x);
		if(nroot(f))ch[p][rc(p)==f]=x;
		fa[ch[f][c]=ch[x][c^1]]=f;
		fa[ch[x][c^1]=f]=x;
		fa[x]=p;
		pushup(f);
		pushup(x);
	}
	inline void splay(int x)
	{
		cnt=0;
		stack[++cnt]=x;
		for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
		while(cnt)pushdown(stack[cnt--]);
		for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
			if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
		pushup(x);
	}
	inline void access(int x)
	{
		for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
	}
	inline int findroot(int x)
	{
		access(x);splay(x);
		while(lc(x))pushdown(x),x=lc(x);
		splay(x);
		return x;
	}
	inline void makeroot(int x)
	{
		access(x);splay(x);reverse(x);
	}
	inline void split(int x,int y)
	{
		makeroot(x);access(y);splay(y);
	}
	inline void link(int x,int y)
	{
		makeroot(x);
		if(findroot(y)!=x)fa[x]=y;
	}
	inline void cut(int x,int y)
	{
		makeroot(x);
		if(findroot(y)==x&&fa[y]==x&&!rc(y))fa[y]=lc(x)=0,pushup(x);
	}
};
LCT T;
#undef lc
#undef rc
template<typename T> inline void read(T &x)
{
	T data=0,w=1;
	char ch=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
	x=data*w;
}
template<typename T> inline void write(T x,char c='

免责声明:内容来源于网络,仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Asp.Net WebAPI Get提交、Post提交处理Jmeter之 forEach 遍历所有值下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章