hdu 2444 The Accomodation of Students(二分匹配 匈牙利算法 邻接表实现)

The Accomodation of Students

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3565    Accepted Submission(s): 1659


Problem 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
 

 

Source

 

题意: 有n个人,m条关系,问通过这些关系判断,所有人是否可以分成两个组,如果可以則求出一组最多多少人。

 

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <math.h>
  5 #include <iostream>
  6 #include <algorithm>
  7 #include <climits>
  8 #include <queue>
  9 #define ll long long
 10 
 11 using namespace std;
 12 
 13 const int N = 20000;
 14 int head[N],total,visit[N];
 15 int link[N],color[250];
 16 
 17 struct nodes
 18 {
 19     int e,next;
 20 } Edge[N];
 21 
 22 
 23 void add(int x,int y)//加边,邻接表形式建图
 24 {
 25     Edge[total].e = y;
 26     Edge[total].next = head[x];
 27     head[x] = total++;
 28 }
 29 
 30 int dfs(int f) //匈牙利算法中的二分匹配dfs实现
 31 {
 32     for(int i  = head[f]; i != -1; i = Edge[i].next)//邻接表遍历与起始点f相连的所有点
 33     {
 34         int s = Edge[i].e; //与起始点相连的点
 35         if(visit[s]) continue;//访问过就跳过
 36         visit[s] = 1;
 37         if(link[s] == -1 || dfs(link[s]))//寻找增广路径
 38         {
 39             link[s] = f ;
 40             return 1;
 41         }
 42     }
 43     return 0;
 44 }
 45 
 46 void init()//初始化
 47 {
 48     total = 0;
 49     memset(head,-1,sizeof(head));
 50     memset(link,-1,sizeof(link));
 51 }
 52 bool bcolor(int u,int x)
 53 {
 54     if(color[u] != -1)//如果从上个点出发过来,发现该点已染色
 55     {
 56         if(color[u] == x)//如果此点颜色与邻点相同
 57             return false; //不是二分图,返回染色失败
 58     }
 59     else
 60     {
 61         color[u] = x^1;//该点未染色,則染与上个点不同的颜色
 62         for(int i = head[u]; i != -1; i = Edge[i].next)//遍历与该点相连的所有边
 63         {
 64             if(!bcolor(Edge[i].e,color[u]))//如果下一层染色失败,則返回失败
 65                 return false;
 66         }
 67     }
 68     return true;
 69 }
 70 bool judge(int n)
 71 {
 72     memset(color,-1,sizeof(color));//先初始化所有点为-1,代表未染色
 73     for(int i = 1; i <= n; i++)//依次检查点是否染过色
 74     {
 75         if(color[i] == -1)//若没访问过,則开始填色
 76         {
 77             if(!bcolor(i,0))
 78                 return false;
 79         }
 80     }
 81     return true;
 82 }
 83 int main(void)
 84 {
 85     int n,i,cnt,m;
 86     while(scanf("%d",&n) != -1)
 87     {
 88         init();
 89         scanf("%d",&m);
 90         for(i = 0; i < m; i++)
 91         {
 92             int x,y;
 93             scanf("%d %d",&x,&y);
 94             add(x,y);
 95             //add(y,x);
 96         }
 97         if(!judge(n)) // 判断是否为二分图
 98         {
 99             printf("No\n");
100         }
101         else //匈牙利算法
102         {
103             for(cnt = 0,i = 1; i <= n; i++)
104             {
105                 memset(visit,0,sizeof(visit));
106                 if(dfs(i))
107                     cnt++;
108             }
109             printf("%d\n",cnt);//若建的双向边則最大匹配数统计了两次,因为是双向的,所以需除以2 ;若建的单向边,則不需要除以2.
110         }
111 
112     }
113     return 0;
114 }

 

posted on 2015-08-10 11:24  鱼泪儿  阅读(209)  评论(0编辑  收藏  举报

导航