hdu 2444 The Accomodation of Students(最大匹配 + 二分图判断)

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

The Accomodation of Students
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

There are a group of students. Some of them may know each other, while others don't. For example, A and B know each other, B and C know each other. But this may not imply that A and C know each other. 
Now you are given all pairs of students who know each other. Your task is to divide the students into two groups so that any two students in the same group don't know each other.If this goal can be achieved, then arrange them into double rooms. Remember, only paris appearing in the previous given set can live in the same room, which means only known students can live in the same room. 
Calculate the maximum number of pairs that can be arranged into these double rooms. 
 

Input

For each data set:  The first line gives two integers, n and m(1<n<=200), indicating there are n students and m pairs of students who know each other. The next m lines give such pairs. 
Proceed to the end of file. 
 

Output

If these students cannot be divided into two groups, print "No". Otherwise, print the maximum number of pairs that can be arranged in those rooms. 
 

Sample Input

4 4 1 2 1 3 1 4 2 3 6 5 1 2 1 3 1 4 2 5 3 6
 

Sample Output

No 3
 
题目大意: 有n个人,和m种关系,代表a和b认识。要求将n个人放入到两个集合中,每个集合中的人互不认识,A集合中的人找B集合的人住房间,两个人一间,且两个人必须认识,问你最多能住多少间房间。
 
判断是否为二分图:在无向图G中,如果存在奇数回路,则不是二分图。否则是二分图。
判断回路奇偶性:把相邻两点染成黑白两色,如果相邻两点出现颜色相同则存在奇数回路。也就是非二分图。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#define N 210

int G[N][N], vis[N], used[N];
int m, n, f, c[N];

bool Find(int u)
{
    int i;
    for(i = 1 ; i <= n ; i++)
    {
        if(!vis[i] && G[u][i])
        {
            vis[i] = 1;
            if(!used[i] || Find(used[i]))
            {
                used[i] = u;
                return true;
            }
        }
    }
    return false;
}

void DFS(int x, int color)
{
    int i;
    for(i = 1 ; i <= n ; i++)
    {
        if(G[x][i])
        {
            if(c[i] == 0)
            {
                c[i] = -color;//将x相邻的点i染成与其不同的颜色
                DFS(i, -color);
            }
            else if(c[i] == color)//如果相邻两点颜色相同则不是二分图
            {
                f = 0;
                return ;
            }
        }
    }
}

int main()
{
    int i, a, b;
    while(~scanf("%d%d", &n, &m))
    {
        memset(G, 0, sizeof(G));
        memset(c, 0, sizeof(c));
        f = 1;
        while(m--)
        {
            scanf("%d%d", &a, &b);
            G[a][b] = G[b][a] = 1;
        }
        c[1] = 1;
        DFS(1, 1);//将1号染成黑色
        if(f == 0)
            printf("No\n");
        else
        {
            int ans = 0;
            memset(used, 0, sizeof(used));
            for(i = 1 ; i<= n ; i++)
            {
                memset(vis, 0, sizeof(vis));
                if(Find(i))
                    ans++;
            }
            printf("%d\n", ans / 2);
        }
    }
    return 0;
}
View Code

 

posted @ 2015-08-11 10:18  午夜阳光~  阅读(225)  评论(0编辑  收藏  举报