hdu 2444 The Accomodation of Students(二分图判断+匈牙利算法)

题意:给定n个学生,他们之间可能互相认识,首先判断能不能将这些学生分为两组,使组内学生不认识;
现想将学生两两分组,且保证每一组的学生都认识,这样分组可达到的最大组数为多大?
即n个点,m条边,要求判断构成的图是否是二分图,是的话求出最大匹配,不是二分图输出“No”。


思路:二分图是这样一个图: 有两顶点集且图中每条边的的两个顶点分别位于两个顶点集中,每个顶点集中没有边相连接。

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

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
const int M=1010;
const int N=4000;
bool g[N][N],vis[N];
int n,m,ans,match[N];
bool bfs()//染色法判断是否为二分图
{
    queue<int> q;
    bool tag[N];
    //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 printf("No\n");
    }
}

你可能感兴趣的:(hdu 2444 The Accomodation of Students(二分图判断+匈牙利算法))