浅谈二分图

(一)二分图匹配

给定一个二分图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;
}

(三)匈牙利算法

用增广路求最大匹配(称作匈牙利算法)
算法轮廓:

    1. 置M为空
    2. 找出一条增广路径P,通过取反操作获得更大的匹配M’代替M
    3. 重复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++;
  }

}

 

猜你喜欢

转载自www.cnblogs.com/yanchaoyi/p/9380614.html