在图论中,二分图(bipartite graph)是一类特殊的图,又称为二部图、偶图、双分图。二分图的顶点可以分成两个互斥的独立集 U 和 V 的图,使得所有边都是连结一个 U 中的点和一个 V 中的点。
给定一个二分图 G,在 G 的一个子图 M 中,M 的边集中的任意两条边都没有共同的端点,则称 M 是一个匹配。
最小点覆盖:选最少的点,满足每条边至少有一个端点被选。
交错路始于非匹配点且由匹配边与非匹配边交错而成。
增广路是始于非匹配点且终于非匹配点的交错路。
特性
二分图中不存在奇环
因为每一条边都是从一个集合走到另一个集合,只有走偶数次才可能回到同一个集合。
König 定理:一个图是二分图当且仅当它的最小顶点覆盖的顶点数等于最大匹配的边数
首先,最小点集覆盖一定 >= 最大匹配,因为假设最大匹配为 n,那么我们就得到了 n 条互不相邻的边,光覆盖这些边就要用到 n 个点。现在我们来思考为什么最小点击覆盖一定 <= 最大匹配。任何一种 n 个点的最小点击覆盖,一定可以转化成一个 n 的最大匹配。因为最小点集覆盖中的每个点都能找到至少一条只有一个端点在点集中的边(如果找不到则说明该点所有的边的另外一个端点都被覆盖,所以该点则没必要被覆盖,和它在最小点集覆盖中相矛盾),只要每个端点都选择一个这样的边,就必然能转化为一个匹配数与点集覆盖的点数相等的匹配方案。所以最大匹配至少为最小点集覆盖数,即最小点击覆盖一定 <= 最大匹配。综上,二者相等。
#include<bits/stdc++.h>usingnamespacestd;constintN=1005,V=500005;intn,m,e,ans,outp[N];intto[V],head[N],nxt[V],tot;booluse[N];intmat[N];voidadd(intx,inty){to[++tot]=y;nxt[tot]=head[x];head[x]=tot;}booldfs(intu){for(inti=head[u];i;i=nxt[i]){intv=to[i];if(use[v]==0){use[v]=1;if(mat[v]==0||dfs(mat[v])){mat[v]=u;returntrue;}}}returnfalse;}intmain(){cin>>n>>m>>e;for(inti=0;i<e;i++){intu,v;cin>>u>>v;add(u,v);}for(inti=1;i<=n;i++){memset(use,0,sizeofuse);// 记得清空 use
if(dfs(i))ans++;// 从左部点 i 出发找增广路
}cout<<ans<<endl;for(inti=1;i<=m;i++){outp[mat[i]]=i;}for(inti=1;i<=n;i++){cout<<outp[i]<<' ';}return0;}