浅谈二分图
Posted yanchaoyi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈二分图相关的知识,希望对你有一定的参考价值。
(一)二分图匹配
给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配。
图中加粗的边是数量为2的匹配。
(一)二分图判定
如果一个图是连通的,可以用如下的方法判定是否是二分图:
在图中任选一顶点v,定义其距离标号为0,然后把它的邻接点的距离标号均设为1,接着把所有标号为1的邻接点均标号为2(如果该点未标号的话),如图所示,以此类推。
标号过程可以用一次BFS实现。标号后,所有标号为奇数的点归为X部,标号为偶数的点归为Y部。
接下来,二分图的判定就是依次检查每条边,看两个端点是否是一个在X部,一个在Y部。
如果一个图不连通,则在每个连通块中作判定。代码如下:
bool judge() { memset(vis,-1,sizeof(vis)); queue<int> q; q.push(1); vis[1]=0; while(!q.empty()) { int v = q.front(); q.pop(); for(int i=1;i<=n;i++) { if(mp[v][i]) { if(vis[i]==-1) { vis[i]=(vis[v]+1)%2; q.push(i); } else if(vis[v]==vis[i]) return false; } } } return true; }
(三)匈牙利算法
用增广路求最大匹配(称作匈牙利算法)
算法轮廓:
- 置M为空
- 找出一条增广路径P,通过取反操作获得更大的匹配M’代替M
- 重复2操作直到找不出增广路径为止
代码如下:
bool dfs(int a)
{
for(int i=1;i<=n;i++)
{
if(mp[a][i]==1&&!visit[i])
{
visit[i]=1;
if(link[i]==0||dfs(link[i]))
{
link[i]=a;
return true;
}
}
}
return false;
}
void hungarian
()
{
int ans=0;
for(int i=1;i<=m;i++)
{
memset(visit,0,sizeof(visit));
if(dfs(i))
ans++;
}
}
以上是关于浅谈二分图的主要内容,如果未能解决你的问题,请参考以下文章