HDU2444(二分图)

hdu2444: http://acm.hdu.edu.cn/showproblem.php?pid=2444

二分图的判断以及二分图的最大匹配

题意:
给定n个学生,他们之间可能互相认识,首先判断能不能将这些学生分为两组,使组内学生不认识;
现想将学生两两分组,且保证每一组的学生都认识,这样分组可达到的最大组数为多?

这道题是赤裸裸的二分图模版题,先判断是不是二分图,在用二分图最大匹配搞。

/** 二分图的判断以及二分图的最大匹配 题意: 给定n个学生,他们之间可能互相认识,首先判断能不能将这些学生分为两组,使组内学生不认识; 现想将学生两两分组,且保证每一组的学生都认识,这样分组可达到的最大组数为多? */
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
const int inf=0x3f3f3f3f;
const int MAX_=206;
int g[MAX_][MAX_];
int match[MAX_];
bool used[MAX_];
int color[MAX_];
int n,m;

/** 我一开始的做法是 直接求一边最大匹配 当每条边都有匹配的时候这个图就是二分图 事实上 这个结论是错的 */
///二分图最大匹配
int dfs(int x)
{
    for(int i=1; i<=n; i++)
    {
        if((!used[i])&&(g[i][x]))
        {
            used[i]=true;
            if((!match[i])||(dfs(match[i])))
            {
                match[i]=x;///这里 我不明白为什么不是
                           ///match[x]=i
                           ///事实上这里跟增广路有关 
                           ///增光路起点与终点都在“i”上
                return 1;
            }
        }
    }
    return 0;
}

///二分图判定
int dfs_(int x,int color_)
{
    color[x]=color_;
    for(int i=1; i<=n; i++)
    {
        if(g[i][x]&&(color[i]==color_))///如果染色过
            return 0;
        if(g[i][x]&&(color[i]==-1))///如果还没有染色过
            if(!dfs_(i,!color_))
                return 0;
    }
    return 1;
}
int main()
{
    #ifdef ONLINE_JUDGE
    #else
    freopen("in1.txt","r",stdin);
    #endif // ONLINE_JUDGE

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(g,0,sizeof(g));
        for(int i=0; i<m; i++)
        {
            int num1,num2;
            scanf("%d%d",&num1,&num2);
            g[num1][num2]=1;
            g[num2][num1]=1;
        }
        int ans=0;
        ///WA fill(match,match+n,0);
        memset(match,0,sizeof(match));
        for(int i=1; i<=n; i++)
        {
            memset(used,false,sizeof(used));
            ///if(match[i]==0&&dfs(i))
            ///为什么这个是错的 当前的匹配边即使不是0
            ///也可能找到增广路 这样的条件使这样程序没有重新匹配的机会
            if(dfs(i))
                ans++;
        }
        bool judge=true;
        memset(color,-1,sizeof(color));
        for(int i=1; i<=n; i++)
        {
            if(color[i]==-1&&dfs_(i,0)==0)
                ///还没有染过色 就去染色 染不了 失败 不是二分图
                judge=false;
        }
        if(!judge)
        {
            puts("No");
        }
        else printf("%d\n",ans/2);
    }

    return 0;
}

你可能感兴趣的:(HDU2444(二分图))