HDU2444

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2444

题目大意:

  n个学生,他们中间有m对互相认识。有两个操作:

  1、把所有人分成两组,每组中的人都互不认识。若该操作能完成,那么请考虑操作2,否则输出“No”;

  2、将互相认识的两个人分配到一间双人房,问最多能分出多少间房。

  其实操作1就是要我们做一个二分图判定,我们用一个DFS就能完成,详见《挑战程序设计竞赛》P97。在确定这是一个二分图的前提下,我们就能根据学生之间的关系写一个匈牙利算法来求最大匹配数,最大匹配数其实就是最多的房间数。由于在程序中,我把每个房间当成了两个来进行匹配,所以最后的最大匹配数要除以2。

AC代码:

 1 #include <cstring>
 2 #include <vector>
 3 #include <cstdio>
 4 using namespace std;
 5 const int maxn=204;
 6 bool link[maxn][maxn], vis[maxn];
 7 int r[maxn],n,color[maxn];
 8 vector<int> G[maxn];
 9 bool finds(int x){
10     for(int i=1;i<=n;i++){
11         if(!vis[i]&&link[x][i]){
12             vis[i]=true;
13             if(r[i]==0||finds(r[i])){
14                 r[i]=x;
15                 return true;
16             }
17         }
18     }
19     return false;
20 }
21 bool dfs(int v,int c){
22     color[v]=c;
23     for(int i=0;i<G[v].size();i++){
24         if(color[G[v][i]]==c)   return false;
25         if(color[G[v][i]]==0&&!dfs(G[v][i],-c)) return false;
26     }
27     return true;
28 }
29 bool yes_no(){
30     for(int i=1;i<=n;i++){
31         if(color[i]==0){
32             if(!dfs(i,1))  return false;
33         }
34     }
35     return true;
36 }
37 int main(){
38     int m,a,b;
39     while(scanf("%d%d",&n,&m)==2){
40         memset(color,0,sizeof(color));
41         memset(link,false,sizeof(link));
42         memset(r,0,sizeof(r));
43         for(int i=1;i<=n;i++)   G[i].clear();
44         while(m--){
45             scanf("%d%d",&a,&b);
46             G[a].push_back(b),G[b].push_back(a);
47             link[a][b]=link[b][a]=true;
48         }
49         if(!yes_no()){
50             printf("No\n");
51             continue;
52         }
53         int ans=0;
54         for(int i=1;i<=n;i++){
55             memset(vis,false,sizeof(vis));
56             if(finds(i))    ans++;
57         }
58         printf("%d\n",ans/2);
59     }
60     return 0;
61 }

 

posted @ 2017-08-29 22:28  Blogggggg  阅读(180)  评论(0编辑  收藏  举报