hdoj 4265 Science! 【二分 + 最大流】【求最大完美匹配数并输出完美匹配】
来源:互联网 发布:维斯布鲁克生涯数据 编辑:程序博客网 时间:2024/06/06 02:25
Science!
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 439 Accepted Submission(s): 119
Special Judge
Problem Description
Welcome, ladies and gentlemen, to Aperture Science. Astronauts, War Heroes, Olympians — you’re here because we want the best, and you are it. That said, it’s time to make some science.
Now, I want each of you to stand on one of these buttons. Well done, we’re making great progress here. Now let’s do it again. Oh, come on - don’t stand on the same button! Move, people! No, no, that button’s only for the Astronauts, you know who you are. What?! You say you can’t do everything I ask? Ok let’s start over. You there, the Programmer, figure out how many times we can do this. And make it quick, we have a lot more science to get through…
Now, I want each of you to stand on one of these buttons. Well done, we’re making great progress here. Now let’s do it again. Oh, come on - don’t stand on the same button! Move, people! No, no, that button’s only for the Astronauts, you know who you are. What?! You say you can’t do everything I ask? Ok let’s start over. You there, the Programmer, figure out how many times we can do this. And make it quick, we have a lot more science to get through…
Input
There will be several test cases in the input. The first line of each case will contain n (2≤n≤80) giving the number of people (and the number of buttons) in the experiment. The next n lines will contain n characters each. If the jth character of the ith line is Y it indicates that the ith person can stand on the jth button (it is Notherwise). The last line of input will be a 0.
Output
For each test case, output k, the maximum number of times everyone can be standing on buttons such that nobody stands on the same button more than once (This might be 0). After that, output k lines. Each line should contain n integers separated by single spaces, where the ith integer describes which person is standing on the ith button. All of the lines should be valid and none of them should put the same person on the same button as a previous line of the same test case. Output no extra spaces, and do not separate answers with blank lines. Note that correct outputs might not be unique.
Sample Input
3YYYNYYYNY2YNYN0
Sample Output
23 1 21 2 30
题意:有N个人和N个位置。给出一个N*N的矩阵,矩阵第i行第j列的字符为Y时则表示第i个人可以坐第j个位置,反之不能。现在要求每个人都找到一个不同的位置,当他们全部找到位置时,一轮游戏结束,他们可以开始新的一轮。在新的一轮里,每个人依旧会去找一个不同的位置,但是每个人不能找已经坐过的位置。
问一共可以进行多少轮这样的游戏,并输出每一轮中1——N位置所在的人。
注意:不能在求出最大方案数ans后,直接跑ans次最大流——找满流边。这样找到的满流边可能不是完美匹配的边。
简单说下对mid值建图:设置超级源点source,超级汇点sink
1,source向每个人建边,容量为mid;
2,每个人向他可以站的位置建边(这里的关系可能由于边的删去而不存在),容量为1;
3,每个位置向sink建边,容量为mid。
实现:
1,二分枚举mid值,建图后判断是否满流,继而求出最大方案数ans;
2,以ans建边,跑一次最大流,去掉非满流边(在N*N矩阵里面修改关系)。
3,跑ans次最大流,每次均以1建边。在跑完一次最大流后,找到所有以人为起点、以位置为终点的满流边,每一条边都对应着一个匹配关系。
4,删边,对于人i为起点,位置j为终点的满连边,在N*N矩阵里面去掉他们的关系。
AC代码:
#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#define MAXN 200#define MAXM 50000#define INF 0x3f3f3f3fusing namespace std;struct Edge{ int from, to, cap, flow, next;};Edge edge[MAXM];int head[MAXN], edgenum, cur[MAXN];char Map[MAXN][MAXN];int dist[MAXN];bool vis[MAXN];int source, sink;int N;bool BFS(int s, int t){ queue<int> Q; memset(dist, -1, sizeof(dist)); memset(vis, false, sizeof(vis)); dist[s] = 0; vis[s] = true; Q.push(s); while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i = head[u]; i != -1; i = edge[i].next) { Edge E = edge[i]; if(!vis[E.to] && E.cap > E.flow) { dist[E.to] = dist[u] + 1; if(E.to == t) return true; vis[E.to] = true; Q.push(E.to); } } } return false;}int DFS(int x, int a, int t){ if(x == t || a == 0) return a; int flow = 0, f; for(int &i = cur[x]; i != -1; i = edge[i].next) { Edge &E = edge[i]; if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(a, E.cap-E.flow), t)) > 0) { edge[i].flow += f; edge[i^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow;}int Maxflow(int s, int t){ int flow = 0; while(BFS(s, t)) { memcpy(cur, head, sizeof(head)); flow += DFS(s, INF, t); } return flow;}void init(){ edgenum = 0; memset(head, -1, sizeof(head));}void addEdge(int u, int v, int w){ Edge E1 = {u, v, w, 0, head[u]}; edge[edgenum] = E1; head[u] = edgenum++; Edge E2 = {v, u, 0, 0, head[v]}; edge[edgenum] = E2; head[v] = edgenum++;}void getMap(int mid){ for(int i = 1; i <= N; i++) { addEdge(source, i, mid); addEdge(i+N, sink, mid); } for(int i = 0; i < N; i++) { for(int j = 0; j < N; j++) { if(Map[i][j] == 'Y') addEdge(i+1, j+1+N, 1); } }}int main(){ while(scanf("%d", &N), N) { for(int i = 0; i < N; i++) scanf("%s", Map[i]); int l = 0, r = N; source = 0, sink = 2*N+1; int ans = 0; while(r >= l)//二分 求最大方案数 { int mid = (l + r) >> 1; init(); getMap(mid); if(Maxflow(source, sink) == mid * N) { ans = mid; l = mid + 1; } else r = mid - 1; } init(); getMap(ans);//以ans建边 Maxflow(source, sink); for(int i = 1; i <= N; i++)//删去多余的边 { for(int j = head[i]; j != -1; j = edge[j].next) { Edge E = edge[j]; if(E.to == source) continue; if(E.cap - E.flow == 1) Map[i-1][E.to-N-1] = 'N';//修改关系 } } printf("%d\n", ans); int num[MAXN];//记录第i个位置是哪个人 for(int i = 0; i < ans; i++) { init(); getMap(1);//以1为容量建边 Maxflow(source, sink); for(int k = 1; k <= N; k++)//枚举每个人 { for(int j = head[k]; j != -1; j = edge[j].next)//找满流的边 { Edge E = edge[j]; if(E.to == source) continue; if(E.cap - E.flow == 0)//只会有一条满流的边 { num[E.to-N] = k; Map[k-1][E.to-1-N] = 'N';//删除关系 break; } } } for(int j = 1; j <= N; j++) { if(j > 1) printf(" "); printf("%d", num[j]); } printf("\n"); } } return 0;}
Science!
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 439 Accepted Submission(s): 119
Special Judge
Problem Description
Welcome, ladies and gentlemen, to Aperture Science. Astronauts, War Heroes, Olympians — you’re here because we want the best, and you are it. That said, it’s time to make some science.
Now, I want each of you to stand on one of these buttons. Well done, we’re making great progress here. Now let’s do it again. Oh, come on - don’t stand on the same button! Move, people! No, no, that button’s only for the Astronauts, you know who you are. What?! You say you can’t do everything I ask? Ok let’s start over. You there, the Programmer, figure out how many times we can do this. And make it quick, we have a lot more science to get through…
Now, I want each of you to stand on one of these buttons. Well done, we’re making great progress here. Now let’s do it again. Oh, come on - don’t stand on the same button! Move, people! No, no, that button’s only for the Astronauts, you know who you are. What?! You say you can’t do everything I ask? Ok let’s start over. You there, the Programmer, figure out how many times we can do this. And make it quick, we have a lot more science to get through…
Input
There will be several test cases in the input. The first line of each case will contain n (2≤n≤80) giving the number of people (and the number of buttons) in the experiment. The next n lines will contain n characters each. If the jth character of the ith line is Y it indicates that the ith person can stand on the jth button (it is Notherwise). The last line of input will be a 0.
Output
For each test case, output k, the maximum number of times everyone can be standing on buttons such that nobody stands on the same button more than once (This might be 0). After that, output k lines. Each line should contain n integers separated by single spaces, where the ith integer describes which person is standing on the ith button. All of the lines should be valid and none of them should put the same person on the same button as a previous line of the same test case. Output no extra spaces, and do not separate answers with blank lines. Note that correct outputs might not be unique.
Sample Input
3YYYNYYYNY2YNYN0
Sample Output
23 1 21 2 30
0 0
- hdoj 4265 Science! 【二分 + 最大流】【求最大完美匹配数并输出完美匹配】
- 二分图求最大匹配数,最完美匹配概念
- 二分图的最大匹配完美匹配
- 【hdoj 3081】Marriage Match II 【并查集orfloyd +完美匹配】or【最大流+二分+并查集】
- 【二分图最大匹配】完美的牛栏
- 二分匹配求最大匹配数和最大匹配值
- HDOJ 2819 - Swap 二分图最大匹配..并输出方法..
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- sqlserver复制数据到另一张表中
- Nginx 常见应用技术指南[Nginx Tips] 第二版
- 台湾国立大学机器学习技术.听课笔记(第一讲):Support Vector Machine
- org.xml.sax.SAXParseException元素内容必须由格式正确的字符数据或标记组成。
- 第一个Angularjs前瑞框架项目
- hdoj 4265 Science! 【二分 + 最大流】【求最大完美匹配数并输出完美匹配】
- Ubuntu 设置Java环境变量
- lintcode-子树
- 黑马程序员——43,String,StringBuffer ,基本数据类型包装对象
- 活出自己的精彩——提高班一年总结
- 【bzoj3680】【吊打XXX】【模拟退火】
- 软件测试分类
- Android-图片选择,压缩,上传,加载 的 实例
- Android UI之控件四步走思路