您的位置:首页 > 其它

hdu 2444(二分图判断+最大匹配)

2014-12-23 11:51 357 查看
题意:n个点,m条边,要求判断构成的图是否是二分图,是的话求出最大匹配。

分析:二分图判断的话用bfs进行染色就行了。因为一个图是二分图的充要条件是图中无奇圈,即图中无长度为奇数的回路,因此,从一个点出发,将它染成黑色(0),再将它相邻的点染成白色(1),然后从相邻的点出发,去染其它的点,当出现颜色相同的两个点相邻时,就可判断该图不是二分图。

求最大匹配即很好办了,直接套匈牙利算法模板。

代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<map>

using namespace std;
const int M=1010;
const int N=4000;
bool g

,vis
;
int n,m,ans,match
;
bool bfs()
{
    queue<int> q;
    bool tag
;
    //memset(tag,false,sizeof(tag));
    memset(vis,false,sizeof(vis));
    for (int j=1;j<=n;j++) if (!vis[j]) { // 遇到没染色的点就从它出发去染色其它点
        q.push(j);
        tag[j]= vis[j]=true;
        while(!q.empty()){
            int t=q.front();  q.pop();
            for (int i=1;i<=n;i++) if (g[t][i] && i!=t)
            {
                if (vis[i]){
                    if (tag[i]==tag[t]) return false;
                } else{
                   tag[i]=!tag[t];
                   q.push(i);
                   vis[i]=true;
                }
            }
        }
    }

    return true;
}
bool dfs(int x)
{
    int i,j;
    for (i=1;i<=n;i++) if (g[x][i] && !vis[i])
    {
        vis[i]=true;
        if (match[i]==-1 || dfs(match[i])){
            match[i]=x;
            return true;
        }
    }
    return false;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        int a,b;
        memset(g,false,sizeof(g));
        memset(match,-1,sizeof(match));
        for (int i=0;i<m;i++) {
            scanf("%d%d",&a,&b);
            g[a][b]=true;
        }
        if (bfs()){
            ans=0;
            for (int i=1;i<=n;i++) {
                memset(vis,false,sizeof(vis));
                if (dfs(i)) ans++;
            }
            printf("%d\n",ans);
        } else puts("No");
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: