POJ 2444 The Accomodation of Students 黑白染色+二分匹配 簡單題

有n個人,編號為1~n,其中有m對朋友,現在給出m對朋友,問能不能把這n個人分成2個組,使得每一個組裡面的人都是互相不認識的?

若不可以,輸出No

若可以,問現在將認識的人兩兩配對,輸出最多可以有多少對

說白了,這道題就是首先要判斷是不是二分圖,不是的話輸出No,是的話輸出最大匹配

判斷二分圖:用黑白染色法,注意,整個關係圖有可能是不連通的,所以要遍歷所有的點

這裡求最大匹配不是用匈牙利算法,而是直接轉化為最大流

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 using namespace std;
  5
  6 const int maxn=210;
  7 const int inf=0x3f3f3f3f;
  8
  9 inline int min(int a,int b)
 10 {
 11     return a<b?a:b;
 12 }
 13
 14 bool link[maxn][maxn];
 15 struct Edge
 16 {
 17     int to,next;
 18 };
 19 Edge edge[maxn*maxn*2];
 20 int head[maxn];
 21 int tot;
 22 bool flag;
 23 int dye[maxn];
 24 int level[maxn];
 25 int iter[maxn];
 26 const int s=0;
 27 int t;
 28
 29 void addedge(int u,int v)
 30 {
 31     edge[tot].to=v;
 32     edge[tot].next=head[u];
 33     head[u]=tot++;
 34 }
 35
 36 void init(int n)
 37 {
 38     memset(link,false,sizeof link);
 39     memset(head,-1,sizeof head);
 40     memset(dye,-1,sizeof dye);
 41     tot=0;
 42     flag=true;
 43 }
 44
 45 void to_dye(int pre ,int u)
 46 {
 47     if(pre==-1)
 48         dye[u]=1;
 49     else
 50         dye[u]=!dye[pre];
 51
 52     for(int i=head[u];~i;i=edge[i].next)
 53     {
 54         int v=edge[i].to;
 55         if(v==pre)
 56             continue;
 57         if(dye[v]!=-1)
 58         {
 59             if(dye[v]!=dye[u])
 60                 continue;
 61             else
 62             {
 63                 flag=false;
 64             }
 65         }
 66         else
 67          to_dye(u,v);
 68     }
 69 }
 70
 71 struct Flow_Edge
 72 {
 73     int to,cap,rev;
 74 };
 75 vector<Flow_Edge>flow_edge[maxn];
 76
 77 void add(int from,int to,int cost)
 78 {
 79     flow_edge[from].push_back((Flow_Edge){to,cost,flow_edge[to].size()});
 80     flow_edge[to].push_back((Flow_Edge){from,0,flow_edge[from].size()-1});
 81 }
 82
 83 void build_graph(int n)
 84 {
 85     for(int i=0;i<=n;i++)
 86         flow_edge[i].clear();
 87
 88     t=n+1;
 89     for(int i=1;i<=n;i++)
 90     {
 91         if(dye[i]==1)
 92             add(s,i,1);
 93         else
 94             add(i,t,1);
 95     }
 96     for(int i=1;i<=n;i++)
 97     {
 98         for(int j=1;j<=n;j++)
 99         {
100             if(i==j)
101                 continue;
102             if(link[i][j]||link[j][i])
103             {
104                 if(dye[i]==1)
105                     add(i,j,1);
106                 else
107                     add(j,i,1);
108                 link[i][j]=false;
109                 link[j][i]=false;
110             }
111         }
112     }
113 }
114
115 void bfs()
116 {
117     memset(level,-1,sizeof level);
118     queue<int>que;
119     while(!que.empty())
120         que.pop();
121     level[s]=1;
122     que.push(s);
123     while(!que.empty())
124     {
125         int u=que.front();
126         que.pop();
127         for(int i=0;i<flow_edge[u].size();i++)
128         {
129             Flow_Edge &e=flow_edge[u][i];
130             if(e.cap>0&&level[e.to]<0)
131             {
132                 level[e.to]=level[u]+1;
133                 que.push(e.to);
134             }
135         }
136     }
137 }
138
139 int dfs(int u,int f)
140 {
141     if(u==t)
142         return f;
143     for(int &i=iter[u];i<flow_edge[u].size();i++)
144     {
145         Flow_Edge &e=flow_edge[u][i];
146         if(e.cap>0&&level[e.to]>level[u])
147         {
148             int d=dfs(e.to,min(e.cap,f));
149             if(d>0)
150             {
151                 e.cap-=d;
152                 flow_edge[e.to][e.rev].cap+=d;
153                 return d;
154             }
155         }
156     }
157     return 0;
158 }
159
160 int max_flow(int n)
161 {
162     int flow=0;
163     while(1)
164     {
165         bfs();
166         if(level[t]==-1)
167             return flow;
168         memset(iter,0,sizeof iter);
169         int f;
170         while(f=dfs(s,inf))
171         {
172             if(f>0)
173                 flow+=f;
174         }
175     }
176 }
177
178 int main()
179 {
180     int n,m;
181     while(~scanf("%d%d",&n,&m))
182     {
183         init(n);
184
185         for(int i=0;i<m;i++)
186         {
187             int u,v;
188             scanf("%d%d",&u,&v);
189             link[u][v]=link[v][u]=true;
190             addedge(u,v);
191             addedge(v,u);
192         }
193
194         for(int i=1;i<=n;i++)
195         {
196             if(dye[i]==-1)
197                 to_dye(-1,i);
198         }
199
200         //printf("eee\n");
201
202         if(!flag)
203         {
204             printf("No\n");
205             continue;
206         }
207         else
208         {
209             build_graph(n);
210             int flow=max_flow(n);
211             printf("%d\n",flow);
212         }
213     }
214     return 0;
215 }

时间: 2024-10-22 08:44:26

POJ 2444 The Accomodation of Students 黑白染色+二分匹配 簡單題的相关文章

HDOJ 题目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): 2943    Accepted Submission(s): 1376 Problem Description There are a group of students. Some of them may know each o

POJ 1466 Girls and Boys 黑白染色 + 二分匹配 (最大独立集) 好题

有n个人, 其中有男生和女生,接着有n行,分别给出了每一个人暗恋的对象(不止暗恋一个) 现在要从这n个人中找出一个最大集合,满足这个集合中的任意2个人,都没有暗恋这种关系. 输出集合的元素个数. 刚开始想,把人看成顶点,若有暗恋的关系,就连一条边,构成一个图 独立集的概念:一个图中两两互不相连的顶点集合 所以这道题,就是要求最大独立集 有:最大独立集+最小顶点覆盖=|V|(顶点的总个数) 那就求最小顶点覆盖了 根据题意: 暗恋的对象性别不同,所以a暗恋b,b暗恋c,c暗恋a这种关系不可能存在 也

HDU 2444 The Accomodation of Students(判断是否是二分图)

题目链接 题意:n个学生,m对关系,每一对互相认识的能住一个房间.问否把这些学生分成两组,要求每组的学生都互不认识.求最多需要多少个房间. 是否能分成两组?也就是说判断是不是二分图,判断二分图的办法,用染色法 把初始点染成黑色,然后与之相连的染成白色,重复,使路径黑白相间, 如果当前点的颜色和与他相连点的颜色相同时,则说明这个图不是二分图 求最多需要多少个房间?也就是求最大匹配数. #include <iostream> #include <cstdio> #include <

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 Submit Status Practice HDU 2444 Description There are a group of students. Some of them may know

【HDOJ】2444 The Accomodation of Students

图论的题目.着色原理+二分图匹配. 1 #include <cstdio> 2 #include <cstring> 3 4 #define MAXN 205 5 6 char map[MAXN][MAXN]; 7 int link[MAXN]; 8 int color[MAXN]; 9 bool visit[MAXN]; 10 int n, m; 11 12 bool dfs(int v, int col) { 13 int i; 14 15 for (i=1; i<=n;

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): 2458    Accepted Submission(s): 1177 Problem Description There are a group of students. Some of them may know each ot

HDU 2444 The Accomodation of Students 二分图判定+最大匹配

题目来源:HDU 2444 The Accomodation of Students 题意:n个人是否可以分成2组 每组的人不能相互认识 就是二分图判定 可以分成2组 每组选一个2个人认识可以去一个双人间 最多可以有几组 思路:二分图判定+最大匹配 #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn = 550; int vis[maxn];

HDU 2444 The Accomodation of Students二分图判定和匈牙利算法

本题就是先判断是否可以组成二分图,然后用匈牙利算法求出最大匹配. 到底如何学习一种新算法呢? 我也不知道什么方法是最佳的了,因为看书本和大牛们写的匈牙利算法详细分析,看了差不多两个小时没看懂,最后自己直接看代码,居然不到半个小时看懂了.然后就可以直接拿来解题啦. 比如topcoder上有这个算法的很详细的分析,真没看懂. 代码居然比分析更清晰了?我也不好下结论. 但是我觉得主要的思想还是有作用的. 说说我对这个算法的理解吧: 1 假设二分图分为两个集合 U, V,那么从一个集合U出发 2 U的一

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): 7086    Accepted Submission(s): 3167 Problem Description There are a group of students. Some of them may know each o