AcWing 算法提高课 二分图
1、性质:二分图,等价于不存在奇数环、用染色法染色没有矛盾。
染色法求二分图模板:

int n,m; const int N=20010; vector<int> adj[N]; vector<int> cost[N]; int color[N];//0表示未染色,1白色,2黑色 bool DFS(int u,int c) { color[u]=c; for(int i=0;i<adj[u].size();i++) { int nxt=adj[u][i]; int w=cost[u][i]; if(color[nxt]) { if(color[nxt]==c) return false; } else { if(!DFS(nxt,3-c)) return false; } } return true; } bool Check() { memset(color,0,sizeof(color)); fore(i,1,n) { if(color[i]==0) { if(!DFS(i,1)) return false; } } return true; } void YD() { cin>>n>>m; while(m--) { int a,b,c;cin>>a>>b>>c; adj[a].pub(b); cost[a].pub(c); adj[b].pub(a); cost[b].pub(c); } Check(); }
2、匈牙利算法求二分图中的最大匹配
匹配:取出来的边,没有公共点,类似找对象,一夫一妻
增广路径:非匹配点开始,走非匹配边和匹配边交替的路径,最后到非匹配点。
可以发现增广路径可以构造出更大的匹配。
最大匹配等价于无增广路径。
匈牙利算法可以在二分图中求出最大匹配
匈牙利算法的本质就是图的深度优先遍历,
思想为,找对象:假设二分图一边全是女生,另一边全是男生,给全部的男生找对象,如果可以找到一个女生没有对象则直接找到,
否则就看能不能将女生的对象分给别的女生,如果能,就将其对象更改,并把女生与当前男生进行匹配。
例题:https://www.acwing.com/problem/content/374/
其中 find函数是匈牙利算法的核心
模板:

const int N = 110; int n, m, k; vector<int> adj[N]; bool st[N]; int match[N]; bool Find(int x) { for (auto nxt : adj[x]) { if (!st[nxt]) { st[nxt] = true; int t = match[nxt]; if (t == 0 || Find(t)) { match[nxt] = x; return true; } } } return false; } void YD() { cin >>n>> m >> k; memset(match, 0, sizeof(match)); fore(i,1,n) adj[i].clear(); while (k--) { int a, b; cin >> a >> b; adj[a].push_back(b); } int res = 0; fore(i, 1, n) { memset(st, 0, sizeof(st)); if (Find(i)) res++; } cout << res << endl; }
注意,集合A中有n个点,集合B中有m个点,adj是A中点向B中点连接的边,match和st是B中点的匹配或state
3、以下性质(二分图)
(1)点覆盖:任意一边至少有一个点被选中。
在二分图中,最小点覆盖等于最大匹配数。
最小点覆盖例题:https://www.acwing.com/problem/content/378/
(2)最大独立集:选出最多的点使得选出的点之间没有边。
最大团:选出最多的点使得选出的点中任意两点之间都有边。
原图的最大独立集就是补图的最大团
在二分图中(!),求最大独立集,等价于去掉最少的点将所有边都破坏掉,即找到最小点覆盖并去掉,即找到最大匹配数并去掉。
最大独立集例题:https://www.acwing.com/problem/content/380/
(3)最小路径点覆盖:对于DAG(有向无环图),用最少的互不相交(点不重复)的路径覆盖全部点。
解决方法:
(1)拆点,将点分为入点和出点,边变为由出点指向入点,此时原图可转化为二分图
此时答案为n-m,其中m为二分图的最大匹配数。
思路:
(1)原图中的每条路径,都对应着二分图中的一个匹配(因为路径不会分叉,二分图中每个点度最多为1)
(2)路径的终点没有出边,对应着左侧的非匹配点,又因为所有点都会被覆盖,所以左侧的非匹配点都对应着一条路径的终点
(3)求原图中的最小路径覆盖,等价于求二分图中,左侧的最少非匹配点数量,即点数n-最大匹配数m
(4)最小路径重复点覆盖:对于DAG,用最少的(点和边可重的)路径覆盖全部点。
方法:
(1)先求原图的传递闭包
(2)原图的最小路径重复点覆盖等价于传递闭包的最小路径点覆盖
(3)可以证明二者中的路径一一对应
(4)转化为求二分图中最大匹配数问题
例题:https://www.acwing.com/problem/content/381/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人