UESTC 1144 Big Brother 二分图、最大匹配

Big Brother

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit  Status

现在有 n n个囚笼,需要关押 m m个犯人,the big brother很担心囚笼的安全性,因为犯人都有自己的想法,他们只想住在特定的囚笼里面,那么

big brother想知道最多 能关押多少个犯人,每个囚笼只能关押一个犯人,一个犯人也只能关押在一个囚笼里面。

Input

第一行 两个整数, N(0N200)  和  M(0M200) N 是犯人的数量, M 是囚笼的数量。

第二行到第 N+1 行 一共  N 行,每行对应一只犯人。第一个数字  (Si)  是这哥犯人愿意待的囚笼的数量  (0SiM)

后面的 Si 个数表示这些囚笼的编号。囚笼的编号限定在区间 (1..M)中,在同一行,一个囚笼不会被列出两次。

 

Output

只有一行。输出一个整数,表示最多能分配到的囚笼的数量.

Sample input and output

Sample Input Sample Output
5 5
1 1
1 2
1 3
1 4
1 5
5

Source

2015 UESTC Training for Graph Theory
The question is from   here.

My Solution

最大匹配问题 匈牙利算法, (似乎也可以用它的改进版,Hopcroft-Karp算法)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 200 + 8;
int n;

vector<int> g[maxn];
int from[maxn], tot;
bool use[maxn];

bool match(int x)
{
    int sz = g[x].size();
    for(int i = 0; i < sz; i++){
        if(!use[g[x][i]]) {
            use[g[x][i]] = true;
            if(from[g[x][i]] == -1 || match(from[g[x][i]])) {
                from[g[x][i]] = x;
                return true;
            }
        }
    }
    return false;
}

int hungary()
{
    tot = 0;
    memset(from, 255, sizeof from);
    for(int i = 1; i <= n; i++){
        memset(use, 0, sizeof use);
        if(match(i))
            ++tot;
    }
    return tot;
}

int main()
{
    int N, M, S, x;
    scanf("%d%d", &N, &M); n = N;
    for(int i = 1; i <= n; i++){
        scanf("%d", &S);
        for(int j = 1; j <= S; j++){
            scanf("%d", &x);
            g[i].push_back(x);
        }
    }
    printf("%d", hungary());
    return 0;
}

Thank you!

你可能感兴趣的:(ACM,图论,二分图,最大匹配,匈牙利算法及其改进版)