【UOJ168】元旦老人与丛林【图论证明】【最大权闭合子图】【dinic动态推流】

本文探讨了如何利用最小割算法解决特定类型的图论问题,具体地,判断一个图是否可以被划分为两个生成森林。文章详细介绍了所需数学概念、算法实现步骤,并提供了一个具体的C++实现案例。

题意:给一张无向图,判断能否分成两个生成森林。

n≤2×103,m≤4×103n\leq 2\times 10^3,m\leq 4\times 10^3n2×103,m4×103

题目中这样的图称为“丛林”,下面以此来简称。

结论 一张图是丛林的充要条件是它的每一个子图 G=(∣V∣,∣E∣)G=(|V|,|E|)G=(V,E)∣E∣≤2∣V∣−2|E|\leq 2|V|-2E2V2

必要性显然。

充分性:考虑归纳法,当 ∣V∣=1|V|=1V=1 时显然成立,∣V∣>1|V|>1V>1 假设结点数小于 ∣V∣|V|V 的满足条件的图都是丛林。

引理1 定义满图为满足 ∣E∣=2∣V∣−2|E|=2|V|-2E=2V2 的图,对于当前图的两个交非空的子图 G1=(V1,E1),G2=(V2,E2)G_1=(V_1,E_1),G_2=(V_2,E_2)G1=(V1,E1),G2=(V2,E2),它们的并也是满图。

证明 设它们的交为 G3=(V3,E3)G_3=(V_3,E_3)G3=(V3,E3),并为 G=(V,E)G=(V,E)G=(V,E)。由假设知 ∣E1∣=2∣V1∣−2,∣E2∣=2∣V2∣−2,∣E3∣≤2∣V3∣−2|E_1|=2|V_1|-2,|E_2|=2|V_2|-2,|E_3|\leq 2|V_3|-2E1=2V12,E2=2V22,E32V32,所以 ∣E∣≥2∣V∣−2|E|\geq 2|V|-2E2V2。又因为 ∣E∣≤2∣V∣−2|E|\leq 2|V|-2E2V2,所以 ∣E∣=2∣V∣−2|E|=2|V|-2E=2V2。得证。

引理2 一个丛林最小的点度数小于 444

证明 显然。

对于一张满足右边的条件的图,它的每一个真子图都是丛林。我们考虑它的一个最小的点的度数,如果是 0,1,20,1,20,1,2,就把这些边连到外面对应个数的生成森林上,得到整张图是丛林。下面讨论度数为 333 的情况。

引理3 当度数为 333 时,设相邻的三个点为 a,b,ca,b,ca,b,c,删掉这个点 uuu 及这三条边后的图为 GGG,那么一定存在 {x,y}⊆{a,b,c}\{x,y\}\subseteq \{a,b,c\}{x,y}{a,b,c} 使得 GGG 中不存在一个满子图包含 x,yx,yx,y

证明 假设 a,b,ca,b,ca,b,c 两两都被一个满子图包含,把这三个满子图合并起来,由引理 1,合并后的图 FFF 也是满子图,即 ∣E(F)∣=2∣V(F)∣−2|E(F)|=2|V(F)|-2E(F)=2V(F)2。我们加入 uuu 和这三条边,就得到了一张 ∣E∣=2∣V∣−1|E|=2|V|-1E=2V1 的图,它是原图的子图,矛盾,得证。

我们在 G1G_1G1 中加入一条边 (x,y)(x,y)(x,y),因为不存在包含 (x,y)(x,y)(x,y) 的满图,所以加入后 G1G_1G1 仍然是丛林。考虑这棵丛林的两棵生成树,在包含 (x,y)(x,y)(x,y) 的树上断掉这条边,然后 uuu 分别通过 x,yx,yx,y 连接两个连通分量,剩下一个直接连,就构造了两棵原图的生产树,原命题得证。


现在我们要判断是否对于每一个子图都有

∣E∣≤2∣V∣−2|E|\leq 2|V|-2E2V2

∣E∣−2∣V∣≤−2|E|-2|V|\leq -2E2V2

就是最大权闭合子图对于每条边建一个点,从 SSS 连边权为 111 的边,向两个端点连 +∞+\infin+ 的边,每个点到 TTT 连边权为 222 的边,跑最小割即可。

设最小割为 ccc,边数为 mmm,我们需要判断是否

m−c≤−2m-c\leq -2mc2

然后你会发现至少有一个大小为 mmm 的割,所以会永远输出 No

冷静分析,这样的原因是空图的存在。所以我们要枚举一个点强制选,也就是断掉对应的边,最后最小割 +2+2+2,当 c−2<mc-2<mc2<m 时输出 No

然后要跑 nnn 次完整的 dinic,会 T。注意到每次流量改变是常数,所以在断掉 (u,v)(u,v)(u,v) 时从 uuuSSSc(u,v)c(u,v)c(u,v) 的流量来模拟退流,然后物理断掉这条边。再从 SSSTTT 跑 dinic,因为是在几乎已经增广完的残余网络上跑的所以很快。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <queue>
#define MAXN 6005
#define MAXM 40005
using namespace std;
const int INF=0x7fffffff;
inline int read()
{
	int ans=0;
	char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
struct edge{int u,v,c;}e[MAXM];
int head[MAXN],cur[MAXN],nxt[MAXM],cnt=1;
inline void insert(int u,int v,int c){e[++cnt]=(edge){u,v,c};nxt[cnt]=head[u];head[u]=cnt;}
inline void addnode(int u,int v,int c){insert(u,v,c),insert(v,u,0);}
int dis[MAXN];
bool bfs(int S,int T)
{
	queue<int> q;
	q.push(T);
	memset(dis,-1,sizeof(dis));
	dis[T]=0;
	while (!q.empty())
	{
		int u=q.front();q.pop();
		for (int i=head[u];i;i=nxt[i])
			if (e[i^1].c&&dis[e[i].v]==-1)
			{
				dis[e[i].v]=dis[u]+1;
				q.push(e[i].v);
				if (e[i].v==S) return true;
			}
	}
	return false;
}
int dfs(int u,int f,int T)
{
	if (u==T||!f) return f;
	int used=0;
	for (int& i=cur[u];i;i=nxt[i])
		if (e[i].c&&dis[u]==dis[e[i].v]+1)
		{
			int w=dfs(e[i].v,min(e[i].c,f),T);
			e[i].c-=w,e[i^1].c+=w;
			f-=w,used+=w;
			if (!f) break;
		}
	if (!used) dis[u]=-1;
	return used;
}
inline int dinic(int S,int T,int f=INF)
{
	int ans=0;
	while (f>ans&&bfs(S,T))
		memcpy(cur,head,sizeof(head)),ans+=dfs(S,f-ans,T);
	return ans;
}
int pos[MAXN];
int solve()
{
	memset(head,0,sizeof(head));
	memset(nxt,0,sizeof(nxt));
	cnt=1;
	int n,m;
	n=read(),m=read();
	int S=n+m+1,T=S+1;
	for (int i=1;i<=m;i++)
	{
		addnode(n+i,read(),INF);
		addnode(n+i,read(),INF);
		addnode(S,n+i,1);
	}
	for (int i=1;i<=n;i++) addnode(i,T,2),pos[i]=cnt;
	int ans=dinic(S,T);
	for (int i=1;i<=n;i++)
	{
		int f=e[pos[i]].c;
		e[pos[i]].c=e[pos[i]^1].c=0;
		if (f) ans-=dinic(i,S,f);
		if (i>1) e[pos[i-1]^1].c=2;
		ans+=dinic(S,T);
		if (ans<m) return puts("No"),0;
	}
	puts("Yes");
	return 0;
}
int main()
{
	for (int T=read();T;T--) solve();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值