HDU 4685 Prince and Princess(二分匹配加点建图+强连通分量)
題目鏈接
Problem Description
There are n princes and m princesses. Princess can marry any prince. But prince can only marry the princess they DO love.
For all princes,give all the princesses that they love. So, there is a maximum number of pairs of prince and princess that can marry.
Now for each prince, your task is to output all the princesses he can marry. Of course if a prince wants to marry one of those princesses,the maximum number of marriage pairs of the rest princes and princesses cannot change.
Input
The first line of the input contains an integer T(T<=25) which means the number of test cases.
For each test case, the first line contains two integers n and m (1<=n,m<=500), means the number of prince and princess.
Then n lines for each prince contain the list of the princess he loves. Each line starts with a integer ki(0<=ki<=m), and then ki different integers, ranging from 1 to m denoting the princesses.
Output
For each test case, first output “Case #x:” in a line, where x indicates the case number between 1 and T.
Then output n lines. For each prince, first print li, the number of different princess he can marry so that the rest princes and princesses can still get the maximum marriage number.
After that print li different integers denoting those princesses,in ascending order.
Sample Input
2
4 4
2 1 2
2 1 2
2 2 3
2 3 4
1 2
2 1 2
Sample Output
Case #1:
2 1 2
2 1 2
1 3
1 4
Case #2:
2 1 2
題意
這道題目更POJ1904很像,但是也不太一樣。
這道題每個人不一定剛好完全匹配,而且題目求得是在不影響最大匹配的前提下每個王子能夠娶的公主編號。
思路
先進(jìn)行一次二分匹配,得到一個匹配數(shù)cnt,公主有M-cnt個還沒有匹配,王子有N-cnt個沒有匹配,這是重新加點(diǎn)建邊匹配數(shù)就達(dá)到N+M-cnt個,這樣原來匹配的還會在同一個聯(lián)通分量里,最后篩一下人
#include <iostream> #include <stdio.h> #include <map> #include <vector> #include <set> #include <queue> #include <stack> #include <cstring> #include <cmath> #include <algorithm> #define lowbit(x) (x & (-x)) #define mem(a, b) memset(a, b, sizeof(a)) #define rep(i, a, n) for (int i = a; i < n; ++i) #define mid ((l + r)>>1) #define lc rt<<1 #define rc rt<<1|1 typedef long long LL; #define maxn 2010 using namespace std; // __int128 read() { __int128 x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } return x * f;} // void print(__int128 x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) print(x / 10); putchar(x % 10 + '0');} int read() {int num = 0, flag = 1;char c = getchar();while (c < '0' || c > '9') flag = (c == '-') ? -1 : 1, c = getchar();while (c >= '0' && c <= '9') num = (num << 3) + (num << 1) + c - '0', c = getchar();return num * flag; } void out(int x) {if (x > 9) out(x / 10);putchar(x % 10 + '0'); }vector<int> g[maxn]; int used[maxn], girl[maxn]; int find(int x) {for (int i = 0, y; i < (int)g[x].size(); ++i) {y = g[x][i];if (used[y]) continue;used[y] = 1;if (girl[y] == 0 || find(girl[y])) {girl[y] = x;return 1;}}return 0; } int dfn[maxn], low[maxn], inStack[maxn], Stack[maxn]; int belong[maxn], ans[maxn]; int all, tot, len; void tarjan(int x) {dfn[x] = low[x] = ++tot;inStack[x] = 1;Stack[++len] = x;for (int i = 0, y; i < (int)g[x].size(); ++i) {y = g[x][i];if (!dfn[y]) {tarjan(y);low[x] = min(low[x], low[y]); }else if (inStack[y]) {low[x] = min(low[x], low[y]);}}if (dfn[x] == low[x]) {++all;int top;while (Stack[len] != x) {top = Stack[len--];belong[top] = all;inStack[top] = 0;}top = Stack[len--];belong[top] = all;inStack[top] = 0;} } int main() { #ifndef ONLINE_JUDGE// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout); #endifios::sync_with_stdio(false);cin.tie(0); cout.tie(0);int T, N, M;scanf("%d", &T);for (int k = 1; k <= T; ++k) {mem(girl, 0);mem(dfn, 0);mem(inStack, 0);for (int i = 0; i < maxn; ++i) g[i].clear();all = len = 0;tot = 1;printf("Case #%d:\n", k);scanf("%d %d", &N, &M);for (int i = 1, t, d; i <= N; ++i) {scanf("%d", &t);while (t--) {scanf("%d", &d);g[i].push_back(d+N);}}int cnt = 0;// first_matchfor (int i = 1; i <= N; ++i) {mem(used, 0);cnt += find(i);}int num = N + M;// add_nodefor (int i = M - cnt; i; --i) {++num;for (int j = 1; j <= M; ++j) {g[num].push_back(j + N);}}// add_nodefor (int i = N - cnt; i; --i) {++num;for (int j = 1; j <= N; ++j) {g[j].push_back(num);}}int L = N+M+M-cnt;mem(girl, 0);for (int i = 1; i <= N; ++i) {mem(used, 0);find(i);}for (int i = N+M+1; i <= L; ++i) {mem(used, 0);find(i);}// build_graphfor (int i = N+1; i <= N+M; ++i) {g[i].push_back(girl[i]);}for (int i = L+1; i <= num; ++i) {g[i].push_back(girl[i]);}for (int i = 1; i <= N; ++i) {if (dfn[i]) continue;tarjan(i);}for (int i = 1; i <= N; ++i) {int sum = 0;for (int j = 0, y; j < (int)g[i].size(); ++j) {y = g[i][j];if (belong[y] == belong[i] && y >= N+1 && y <= N+M) ans[sum++] = y;}sort(ans, ans+sum);printf("%d", sum);for (int j = 0; j < sum; ++j) {printf(" %d", ans[j]-N);}puts("");}}return 0; }總結(jié)
以上是生活随笔為你收集整理的HDU 4685 Prince and Princess(二分匹配加点建图+强连通分量)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POJ 1904 King's Ques
- 下一篇: hihoCoder #1467 : 2-