hrbeu 哈工程The Accomodation of Students

经典题目,HDU上也有,给定一个无向图,先判断是否为二分图,不是输出No,是的话,输出最大匹配,算是一个模板题

1.一个图不存在奇环则是二分图

2.二分图最大匹配用匈牙利算法

 

#include <cstdio>
#include <cstring>
#define N 210
int g[N][N];  //无向图领接表
int mat[N],cov[N],vis[N],c[N];
int n,m;

void input()
{
    memset(g,0,sizeof(g));
    for(int i=1; i<=m; i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        int t;
        t=++g[u][0];
        g[u][t]=v;
        t=++g[v][0];
        g[v][t]=u;
    }
    return ;
}

int dfs(int u ,int p) //u是当前顶点,p是它的前驱,c表示奇偶
{
    vis[u]=1;
    for(int i=1; i<=g[u][0]; i++)
    {
        int v=g[u][i];
        if(v==p) continue;   //如果是前驱跳过,不能走回头
        if(vis[v]==0)       //还没访问过的点,直接访问
        {
            c[v]=!c[u];
            if(dfs(v,u)) 
                return 1;
        }
        else if(vis[v]==1)  //已经访问过,那么就是环,那么就判断是不是奇环
        {
            if( c[u]==c[v] )  //加上成环的边后是奇数,那么就是奇环
                return 1;
        }
    }
    return 0;
}

int find(int u)
{
    for(int i=1; i<=g[u][0]; i++)
    {
        int v=g[u][i];
        if(!cov[v])
        {
            cov[v]=1;
            if(!mat[v] || find(mat[v]))
            {
                mat[v]=u;
                return 1;
            }
        }
    }

    return 0;
}
void max_match()
{
    int ans=0;
    memset(mat,0,sizeof(mat));
    for(int i=1; i<=n; i++)
    {
        memset(cov,0,sizeof(cov));
        ans+=find(i);
    }
/*
    printf("mat数组\n");
    for(int i=1; i<=n; i++)
        printf("%d ",mat[i]);
    printf("\n");
    printf("ans=%d\n",ans);
*/

    printf("%d\n",ans/2);
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        input();
        memset(vis,0,sizeof(vis));
        memset(c,0,sizeof(c));
        int flag=1;
        for(int i=1; i<=n; i++)
            if(!vis[i])
            {
                if(dfs(i,0))
                {flag=0; break;}
            }
        if(!flag)
            printf("No\n");
        else
            max_match();
    }
    return 0;
}
posted @ 2012-11-26 23:45  Titanium  阅读(277)  评论(0编辑  收藏  举报