日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU 4685 Prince and Princess(二分匹配加点建图+强连通分量)

發布時間:2024/4/18 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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很像,但是也不太一樣。
這道題每個人不一定剛好完全匹配,而且題目求得是在不影響最大匹配的前提下每個王子能夠娶的公主編號。

思路

先進行一次二分匹配,得到一個匹配數cnt,公主有M-cnt個還沒有匹配,王子有N-cnt個沒有匹配,這是重新加點建邊匹配數就達到N+M-cnt個,這樣原來匹配的還會在同一個聯通分量里,最后篩一下人

#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; }

總結

以上是生活随笔為你收集整理的HDU 4685 Prince and Princess(二分匹配加点建图+强连通分量)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。