1904 Kings Quest(强连通分量+二分图匹配)

题目大意:有N个帅哥和N个美女,现在给出每个帅哥所喜欢的美女的编号,和一个帅哥和美女的完美匹配 问每个帅哥可以娶多少个美女,且当他娶完这个美女后,剩下的人还可以完美匹配

解题思路:神题啊,,给一个大神的详细解答 具体是这样的,首先先建边,把帅哥和能娶到的美女连边,再把完美匹配的美女和帅哥连边,这样就形成了一张有向图了 接着,找出这张有向图的所有强连通分量,在强连通分量里面的帅哥都可以娶到自己喜欢的美女,且娶完这个美女后,不会影响到其他人 为什么呢? 假设xi为帅哥,yi和yj为美女,假设给定的完美匹配中xi和yi匹配。 现在,我们想让xi和yj匹配,按照二分图匹配,先要找到一条增广链 因为要完美匹配,所以这条增广链最后肯定会指向yi的,那如果把yi再连向xi,是不是就形成了一个环了,那这个环肯定是一个强连通分量了。 所以说,如果xi可以选择yj,那么xi和yj必定是在同一个连通分量里面了

;Edge{int from, to, next;}E[M];int pre[N], sccno[N], stack[N], lowlink[N], head[N];int n, m, dfs_clock, scc_cnt, top, tot;int love[S][S];void dfs(int u) {pre[u] = lowlink[u] = ++dfs_clock;stack[++top] = u;int v;for (int i = head[u]; i != -1; i = E[i].next) {v = E[i].to;if (!pre[v]) {dfs(v);lowlink[u] = min(lowlink[u], lowlink[v]);}else if (!sccno[v]) {lowlink[u] = min(lowlink[u], pre[v]);}}if (lowlink[u] == pre[u]) {scc_cnt++;while (1) {v = stack[top–];sccno[v] = scc_cnt;if (v == u)break;}}}vector<int> v[N];void solve() {memset(pre, 0, sizeof(pre));memset(sccno, 0, sizeof(sccno));dfs_clock = scc_cnt = top = 0;for (int i = 0; i < 2 * n; i++)if (!pre[i])dfs(i);for (int i = 0; i < n; i++)v[i].clear();for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if (sccno[i] == sccno[j + n] && love[i][j])v[i].push_back(j + 1);}printf(“%d”, v[i].size());for (int j = 0; j < v[i].size(); j++)printf(” %d”, v[i][j]);printf(“\n”);}}void AddEdge(int u, int v) {E[tot].from = u;E[tot].to =v;E[tot].next = head[u];head[u] = tot++;}void init() {memset(head, -1, sizeof(head));memset(love, 0, sizeof(love));tot = 0;int t, u, v;for (u = 0; u < n; u++) {scanf(“%d”, &t);while (t–) {scanf(“%d”, &v);love[u][v – 1] = true;AddEdge(u, v + n – 1);}}for (int i = 0; i < n; i++) {scanf(“%d”, &v);AddEdge(v – 1 + n, i);}}int main() {while (scanf(“%d”, &n) != EOF) {init();solve();}return 0;}

战胜困难,走出困境,成功就会属于你。

1904 Kings Quest(强连通分量+二分图匹配)

相关文章:

你感兴趣的文章:

标签云: