hdu 4685 二分匹配+强连通分量
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 4685 二分匹配+强连通分量相关的知识,希望对你有一定的参考价值。
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4685
题解:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<vector> 5 #include<stack> 6 #include<algorithm> 7 using namespace std; 8 9 const int maxn = 2222; 10 11 int scan() { 12 int ret = 0, flag = 0; char ch; 13 if ((ch = getchar()) == ‘-‘) flag = 1; 14 else if (ch >= ‘0‘&&ch <= ‘9‘) ret = ch - ‘0‘; 15 while ((ch = getchar()) >= ‘0‘&&ch <= ‘9‘) ret = ret * 10 + ch - ‘0‘; 16 return flag ? -ret : ret; 17 } 18 19 void out(int x) { 20 if (x>9) out(x / 10); 21 putchar(x % 10 + ‘0‘); 22 } 23 24 int _t[maxn], lef[maxn]; 25 26 int n, m; 27 28 vector<int> G[maxn],G2[maxn]; 29 30 bool match(int u) { 31 for (int i = 0; i < G[u].size(); i++) { 32 int v = G[u][i]; 33 if (!_t[v]) { 34 _t[v] = 1; 35 if (lef[v]==-1 || match(lef[v])) { 36 lef[v] = u; 37 return true; 38 } 39 } 40 } 41 return false; 42 } 43 44 void BM() { 45 for (int i = 0; i < n; i++) { 46 memset(_t, 0, sizeof(_t)); 47 match(i); 48 } 49 //for (int i = 0; i < m; i++) { 50 // printf("lef[%d]:%d\n", i + 1, lef[i]+1); 51 //} 52 } 53 54 int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt; 55 stack<int> S; 56 57 void dfs(int u) { 58 pre[u] = lowlink[u] = ++dfs_clock; 59 S.push(u); 60 for (int i = 0; i < G2[u].size(); i++) { 61 int v = G2[u][i]; 62 if (!pre[v]) { 63 dfs(v); 64 lowlink[u] = min(lowlink[u], lowlink[v]); 65 } 66 else if (!sccno[v]) { 67 lowlink[u] = min(lowlink[u], pre[v]); 68 } 69 } 70 if (lowlink[u] == pre[u]) { 71 scc_cnt++; 72 for (;;) { 73 int x = S.top(); S.pop(); 74 sccno[x] = scc_cnt; 75 if (x == u) break; 76 } 77 } 78 } 79 80 void find_scc(int n) { 81 dfs_clock = scc_cnt = 0; 82 memset(sccno, 0, sizeof(sccno)); 83 memset(pre, 0, sizeof(pre)); 84 for (int i = 0; i < n; i++) { 85 if (!pre[i]) dfs(i); 86 } 87 } 88 89 int vis[maxn]; 90 void solve() { 91 //build 92 memset(vis, 0, sizeof(vis)); 93 int tot_n = n; 94 for (int i = 0; i < m; i++) { 95 if (lef[i] == -1) { 96 lef[i] = tot_n++; 97 } 98 vis[lef[i]] = 1; 99 } 100 int tot_m = m; 101 for (int i = 0; i < tot_n; i++) { 102 if (vis[i] == 0) lef[tot_m++] = i; 103 } 104 for (int i = 0; i < n; i++) { 105 for (int j = 0; j < G[i].size(); j++) { 106 int v = G[i][j]; 107 G2[i].push_back(v + tot_n); 108 } 109 } 110 for (int i = n; i < tot_n; i++) { 111 for (int v = 0; v < m; v++) { 112 G2[i].push_back(v + tot_n); 113 } 114 } 115 for (int i = m; i < tot_n; i++) { 116 for (int v = 0; v < tot_n; v++) { 117 G2[v].push_back(i+tot_n); 118 } 119 } 120 for (int i = 0; i < tot_n; i++) { 121 G2[i + tot_n].push_back(lef[i]); 122 } 123 124 //printf("tot_n:%d\n", tot_n); 125 //for (int i = 0; i < tot_n * 2; i++) { 126 // printf("%d:", i + 1); 127 // for (int j = 0; j < G2[i].size(); j++) { 128 // int v = G2[i][j]; v++; 129 // printf("%d ", v); 130 // } 131 // printf("\n"); 132 //} 133 134 //solve 135 find_scc(tot_n*2); 136 137 //for (int i = 0; i < tot_n * 2; i++) { 138 // printf("sccno[%d]:%d\n", i + 1, sccno[i]); 139 //} 140 141 //print 142 for (int i = 0; i < n; i++) { 143 vector<int> ans; 144 for (int j = 0; j < G[i].size(); j++) { 145 int v = G[i][j]; 146 if (sccno[i] == sccno[v + tot_n]) ans.push_back(v); 147 } 148 sort(ans.begin(), ans.end()); 149 out(ans.size()); 150 for (int i = 0; i < ans.size(); i++) { 151 putchar(‘ ‘); 152 out(ans[i] + 1); 153 } 154 putchar(‘\n‘); 155 } 156 } 157 158 void init() { 159 for (int i = 0; i < maxn; i++) G[i].clear(),G2[i].clear(); 160 memset(lef, -1, sizeof(lef)); 161 } 162 163 int main() { 164 int tc,kase=0; 165 tc = scan(); 166 while (tc--) { 167 init(); 168 n = scan(); m = scan(); 169 int ct,v; 170 for (int i = 0; i < n; i++) { 171 ct = scan(); 172 for (int j = 0; j < ct; j++) { 173 v = scan(); v--; 174 G[i].push_back(v); 175 } 176 } 177 printf("Case #%d:\n", ++kase); 178 BM(); 179 solve(); 180 } 181 return 0; 182 }
以上是关于hdu 4685 二分匹配+强连通分量的主要内容,如果未能解决你的问题,请参考以下文章
Prince and Princess HDU - 4685(匹配 + 强连通)
HDU4685 Prince and Princess强连通