hdu 4685 Prince and Princess(二分图匹配 + 强连通)
2015-11-13 11:11
447 查看
题目链接:hdu 4685 Prince and Princess
解题思路
K为当前最大匹配数,王子增加M-K个虚拟点用来匹配没有配对成功的公主,公主增加N-K的虚拟点用来匹配没有配对成功的王子,然后从公主建一条反向边到其配对的王子,做一次强连通,属于同一联通分量的王子和公主可以配对。代码
#include <cstdio> #include <cstring> #include <vector> #include <stack> #include <algorithm> using namespace std; const int maxn = 2005; /* Strong connected */ stack<int> S; vector<int> G[maxn]; int dfsclock, cntscc, sccno[maxn], pre[maxn]; int dfs(int u) { int lowu = pre[u] = ++dfsclock; S.push(u); for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if (!pre[v]) { int lowv = dfs(v); lowu = min(lowu, lowv); } else if (!sccno[v]) lowu = min(lowu, pre[v]); } if (lowu == pre[u]) { cntscc++; while (true) { int x = S.top(); S.pop(); sccno[x] = cntscc; if (x == u) break; } } return lowu; } void findSCC(int n) { dfsclock = cntscc = 0; memset(pre, 0, sizeof(pre)); memset(sccno, 0, sizeof(sccno)); for (int i = 0; i < n; i++) if (!pre[i]) dfs(i); } int N, M, K, BW, L[maxn]; bool T[maxn]; bool match(int u) { for (int i = 0; i < G[u].size(); i++) { int v = G[u][i] - BW; if (!T[v]) { T[v] = true; if (!L[v] || match(L[v])) { L[v] = u; return true; } } } return false; } int KM (int n) { int ret = 0; memset(L, 0, sizeof(L)); for (int i = 1; i <= n; i++) { memset(T, false, sizeof(T)); if (match(i)) ret++; } return ret; } void init () { scanf("%d%d", &N, &M); BW = N + M; for (int i = 1; i <= BW * 2; i++) G[i].clear(); int k, x; for (int i = 1; i <= N; i++) { scanf("%d", &k); while (k--) { scanf("%d", &x); G[i].push_back(x+BW); } } K = KM(N); for (int i = 1; i <= M-K; i++) { for (int j = 1; j <= M; j++) G[N+i].push_back(j+BW); } for (int i = 1; i <= N; i++) { for (int j = 1; j <= N-K; j++) G[i].push_back(M+j+BW); } int tmp = KM(N+M-K); for (int i = 1; i <= N+M-K; i++) G[i+BW].push_back(L[i]); } int main () { int cas; scanf("%d", &cas); for (int kcas = 1; kcas <= cas; kcas++) { init(); findSCC(N+M-K); printf("Case #%d:\n", kcas); vector<int> ans; for (int i = 1; i <= N; i++) { ans.clear(); for (int j = 0; j < G[i].size(); j++) { int v = G[i][j]; if (v - BW > M) continue; if (sccno[i] == sccno[v]) ans.push_back(v-BW); } sort(ans.begin(), ans.end()); printf("%lu", ans.size()); for (int i = 0; i < ans.size(); i++) printf(" %d", ans[i]); printf("\n"); } } return 0; }
相关文章推荐
- java8的接口新特性(可以有方法体的接口)
- 使用ajaxfileupload插件笔记
- AngularJS模块加载
- ReactiveCocoa & MVVM
- System.Transactions.TransactionException: 该伙伴事务管理器已经禁止了它对远程/网络事务的支持。
- linux 各种桌面环境图片一瞥
- int 和Integer的区别
- Coding a Horizontal Navigation Bar with jQuery Dropdown Menus
- 转载RabbitMQ入门(1)--介绍
- SQLServer中统计所有表记录数
- mktime为什么这么慢
- iOS开发提高效率之:使用CocoaPods管理依赖库
- OV9650摄像头驱动略析
- SpringBoot学习(三),两种启动方式-以main方法启动和在tomcat里启动
- 五笔
- Spring集成Quartz定时任务框架介绍和Cron表达式详解
- Chapter2 Describing Physical Memory
- android ScrollView自动滑到顶部
- 进程和线程的概念和区别
- 淘宝奇门接口PHP例子