二分图 笔记

二分图同时满足 不存在奇数环 和 染色法不矛盾。

二分图的判定:染色法 O(n)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10, M = 2e6 + 10;
struct
{
	int to, next;
}e[M];
int top, h[N], color[N], n, m;

void add(int x, int y)
{
	e[++top] = {y, h[x]};
	h[x] = top;
}

bool dfs(int x, int c)
{
	color[x] = c;
	for (int i = h[x]; i ; i = e[i].next)
	{
		int y = e[i].to;
		if (!color[y])
			if (dfs(y, (c == 1 ? 2 : 1))) return true;
		else if (color[y] == c) return true;
	}
	return false;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n >> m;
	for (int i = 1; i <= m; i ++)
	{
		int x, y; cin >> x >> y;
		add(x, y); add(y, x);
	}
	bool flag = false;
	for (int i = 1; i <= n; i ++)
		if (!color[i])
			if (dfs(i, 1))
			{
				flag = true;
				break;
			}
	cout << (flag ? "No" : "Yes");
	
	return 0;
}

最大匹配:匈牙利算法(贪心 + dfs, O(nm) )

① 若二分图中有一子图满足任意两条边没有公共节点,则称为一组匹配。

② 边数最多的子图为该二分图的最大匹配。

③ 增广路:从一非匹配点出发,走交替路(非匹配边 -> 匹配边 -> 非匹配边 ...),最后到达另一非匹配点的路径。
用处 :使当前匹配边数量 + 1,即转换该路径上的匹配边和非匹配边

不断对每个点找增广路增加匹配边,找不到增广路时(等价、判定条件),达到最大匹配。

#include <bits/stdc++.h>
#define re register int 
using namespace std;
const int N = 1e3 + 10, M = 5e4 + 10;
struct edge
{
	int to, next;
}e[M];
int top, h[N];
int a, b, m, ans, match[N];
bool vis[N];

inline void add(int x, int y)
{
	e[++ top] = (edge){y, h[x]};
	h[x] = top;
	return;
}

bool dfs(int u)
{
	for (re i = h[u]; i; i = e[i].next)
	{
		int v = e[i].to;
		if (vis[v]) continue;
		vis[v] = true;
		if (!match[v] || dfs(match[v]))
		{
			match[v] = u;
			return true;
		}
	}
	return false;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> a >> b >> m;
	for (re i = 1; i <= m; i ++)
	{ 
		int x, y; cin >> x >> y;
		add(x, y);
	}
	for (re i = 1; i <= a; i ++)
	{
		memset(vis, false, sizeof(vis));
		if (dfs(i)) ans ++;
	}
	cout << ans; //最大匹配的边数
	
	return 0;
}

最大匹配模型要素:
节点能分成两个独立的集合, 每个集合内没有边
每个节点只能与一条匹配边相连

拓展

完备匹配:一二分图左右部均为 N 个节点。若其最大匹配包含 N 条匹配边,则称该图具有完备匹配。

多重匹配(广义的匹配问题)

一二分图左部有 N 个点,右部有 M 个点。

选出尽量多的边,满足左部第 i 个点至多与 \(kl_i\) 条边相连,右部同理。

\(kl_i = kr_i = 1\) 时,就是二分图的最大匹配。

方法:拆点法 acwing374. 导弹防御塔


最小点覆盖

对任意无向图,存在一最小点集,使每条边都至少有一个端点在该集合中,则称该集合为最小点覆盖。

在二分图中,总有 最小点覆盖 = 最大匹配数

最小点覆盖模型要素:
每条边有两个端点,二者至少选一个

最大独立集

对任意无向图,存在一最大点集,使任意两点间都没有直接的边相连,则称该集合为最大独立集。

在二分图中,
选出最多的点构成独立集 \(\Leftrightarrow\) 去掉最少的点,使剩下的点之间没有边 \(\Leftrightarrow\) 用最少的点覆盖所有边

所以,最大独立集 = 总点数 - 最小点覆盖(最大匹配数)

最小路径点覆盖

DAG(有向无环图)中,用最少的不相交的简单路径覆盖图中所有的点,称作最小路径点覆盖。

方法:拆点法构造二分图,DAG 中不存在自环,便可以将所有点拆成 i 和 i',左部表示每个点的出点,右部表示每个点的入点,即若有 u -> v ,在拆点二分图中连 u -> v'

对于点数为 n 的 有向无环图 G 的最小路径点覆盖,有:

路径数 = n - 拆点二分图的最大匹配数

posted @ 2024-04-15 13:17  Zhang_Wenjie  阅读(19)  评论(0)    收藏  举报