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);
#endif
    ios::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_match
        for (int i = 1; i <= N; ++i) {
            mem(used, 0);
            cnt += find(i);
        }
        int num = N + M;
        // add_node
        for (int i = M - cnt; i; --i) {
            ++num;
            for (int j = 1; j <= M; ++j) {
                g[num].push_back(j + N);
            }
        }
        // add_node
        for (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_graph
        for (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;
}

猜你喜欢

转载自blog.csdn.net/henuyh/article/details/88559903