二分图 学习笔记

怎么联合省选前啥都不会,但还是要尽力。

不放歌了,更加清爽一些。

定义

  • 一个无向图,满足他的所有点可以被划分成两个集合 V1,V2V1,V2,相同集合内的点没有连边。这是从点的角度。

  • 一个无向图,每一条边所对应的两个点属于不同的集合 V1,V2V1,V2。这是从边的角度,个人感觉这个角度好理解。

这两个点集称为互补点集,这个图就是二分图,可以写作 G(V1,V2,E)G(V1,V2,E),如果 V1V1 所有节点和 V2V2 邻接,那么这就是完全二分图,记 V1=n,V2=m|V1|=n,|V2|=m完全二分图可以写成 Kn,mK_{n,m},其中 K1,nK_{1,n} 就是菊花图。

注意,V1,V2V1,V2 的划分不一定唯一。

同时,以下定义都是二分图:

  • 无向图 GG 中没有奇环。(偶环可以二染色,图可以看成偶环缩点+DAG,现对DAG染色,然后对偶环染色即可。)
  • 无向图 GG 可以二染色。(可以二染色就代表了每一条边对应的两个点属于不同集合。)

容易发现,树是二分图。

二分图染色

首先你要判断这个图是一个二分图。

染色的目的是要方便表示相对的关系,更加直观一些。

从边的角度考虑,很显然,如果确定了当前点的颜色,那么与他相连的点的颜色就能确定了。

那你不断染色以后,如果发现冲突(相邻点颜色相同),那就必然无解。

二分图匹配

匹配:定义如果一个无向图 GG 中找到一个边集 MM,使得 MM 中任意两条边不邻接(没有公共点),那么 MM 就是 GG 的一个 匹配

如果 M|M| 是所有方案中最大的,那说明 MM 是二分图的最大匹配

如果 GG 中所有的点都和 MM 关联,那么这个匹配 MM 就是完美匹配,因为如果此时再加边的话就会有两条边邻接了,所以 完美匹配 一定是 最大匹配

有结论:若 GG 有完美匹配,说明 G=2M|G|=2|M|。因为每次新加边都有新的两个点。

一种理解方式,你往 MM 加边的过程,每次就宣告了不能选取某两个点的所有边了。

如果 G=(V1,V2,E)G=(V1,V2,E),假定V1<V2|V1|<|V2|MM 是一个匹配满足 M=V1|M|=|V1| 的话,MM 就是一个 完备匹配完备匹配 也是 最大匹配,因为你每连一条边就用掉了 V1V1 的一个点,最多就是 V1|V1| 个了,如果你从 V2V2 开始不优。

霍尔定理G=(V1,V2,E)G=(V1,V2,E) 有完备匹配的充要条件是(可以互推):对于任意正整数 k<=V1k<=|V1|,满足 V1V1 中任意 kk 个点和 V2V2 至少 kk 个点相连。

我所能知道的只有两个:

  • 如果不具备这样的条件的话,那么 V1V1 多个点可以连向 V2V2 一个点,这时候 MM 大小就一定不符合,就不是完备匹配。

实现(寻找二分图最大匹配):

匈牙利算法。

因为是要求找到的边尽可能多,那么实际上就是能覆盖到的点尽可能多。尽量从边的角度考虑,再推到点。

二分图最大匹配对点的最大限制就是一个点仅可以对应一个点,同时保证数量最大。

定义一个数组 matmat 表示和 vv 匹配的点,初始值是 1-1

流程:

  1. V1V1 中找到一个未尝试的点 uu
  2. 找到一条和 uu 关联但是没尝试过的边 vv
  3. 如果 vv 未被匹配,那么 uuvv 匹配,跳到 66
  4. 如果 vv 匹配过了,不妨让 matvmat_v 重新进行一个匹配(回到 22),如果能匹配成功,那么 uuvv 匹配,到 66 ,否则到 55
  5. 如果还有没有尝试的边,接着尝试(跳到 22),否则到 66
  6. 如果还有没有尝试的点,到 11,否则结束。

正确性保证是霍尔定理。

尝试了 V1|V1| 个点,然后最坏情况下每条边都试一次,时间是 O(V1E)O(|V1||E|) 的。

bool color(int u){
	vis[u]=1;
	for(int i=0;i<g[u].size();i++){
		int v=g[u][i];
		if(mat[v]==-1||(vis[mat[v]]==false&&color(mat[v]))){// 防止走环回来 
			mat[v]=u,mat[u]=v;
			return 1;
		}
	}
	return 0;
}
void Match(){
	memset(mat,-1,sizeof(mat));
	int ans=0;
	for(int i=1;i<=n;i++){
		if(mat[i]==-1){
			memset(vis,0,sizeof(vis));
			if(color(i))	ans++;
		}
	}
	cout<<ans<<endl;
}

P1330 封锁阳光大学

二分图染色板,但是自己一开始还看错结论,抽象。

我们不妨把任意一点赋值为 11,很显然,和他周围的点就要赋值成 00,这样一直染色下去即可。如果发现冲突就是无解。

因为你染色这个东西是相对的,所以你可以认为你在所有 11 的位置放了河蟹,也可以认为你在所有 00 的位置放了河蟹,两种情况取最小即可。

posted @   June_Failure  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示