POJ-1466-Girls and Boys(二分图最大独立集)

http://blog.csdn.net/sdj222555/article/details/7426592

大意就是有n个人,每个人与其他的某几个人有关系,这个关系且称为浪漫关系,然后最后求一个最大的集合,使得集合中所有的人两两之间都不存在浪漫关系。

 

看到之后就可以发现,这是一道非常明显的最大独立集的问题,可以转化为二分图来做,还是最经典的拆点建图,然后根据定理,最大独立集=顶点数-最小点覆盖数。  而对于这道题来说,我们可以发现这个浪漫关系是相互的。

而我们的建图中,按理来说应该是一边是男的点,一边是女的点这样连边,但是题目中没说性别的问题。

只能将每个点拆成两个点,一个当作是男的点,一个当作是女的点了,然后连边。由于关系是相互的,这样就造成了边的重复。也就是边集是刚才的二倍,从而导致了最大匹配变成了二倍。

那么 ,最大独立集=顶点数-最大匹配/2,所以最终答案就呼之欲出了。

// File Name: 1466.cpp
// Author: zlbing
// Created Time: 2013/2/24 1:00:15

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define MAXN 505
int Left[MAXN];
int w[MAXN][MAXN];
bool S[MAXN],T[MAXN];
int N;
bool match(int i)
{
    S[i]=true;
    for(int j=1;j<=N;j++)if(w[i][j]&&!T[j])
    {
        T[j]=true;
        if(Left[j]==0||match(Left[j]))
        {
            Left[j]=i;
            return true;
        }
    }
    return false;
}

int main(){
    while(~scanf("%d",&N))
    {
        int a,b,c;
        CL(w,0);
        CL(Left,0);
        for(int i=0;i<N;i++)
        {
            scanf("%d: (%d)",&a,&b);
            for(int j=0;j<b;j++)
            {
                scanf("%d",&c);
                w[a+1][c+1]=1;
            }
        }
        int sum=0;
        for(int i=1;i<=N;i++)
        {
            CL(S,0);
            CL(T,0);
            if(match(i))sum++;
        }
        printf("%d\n",N-(sum/2));
    }
    return 0;
}

 

posted @ 2013-02-24 01:15  z.arbitrary  阅读(224)  评论(0编辑  收藏  举报