hdu 4685 二分匹配+强连通分量

Posted

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 二分匹配+强连通分量的主要内容,如果未能解决你的问题,请参考以下文章

HDU 4685 强联通分量+网络流

Prince and Princess HDU - 4685(匹配 + 强连通)

HDU4685 Prince and Princess强连通

HDU 3861 The King’s Problem 最小路径覆盖(强连通分量缩点+二分图最大匹配)

hdu3861 强连通分量缩点+二分图最最小路径覆盖

Luogu3731 HAOI2017新型城市化(二分图匹配+强连通分量)