codevs 2776 寻找代表元

 时间限制: 1 s
 空间限制: 256000 KB
 题目等级 : 黄金 Gold
 
 
题目描述 Description

广州二中苏元实验学校一共有n个社团,分别用1到n编号。
广州二中苏元实验学校一共有m个人,分别用1到m编号。每个人可以参加一个或多个社团,也可以不参加任何社团。
每个社团都需要选一个代表。谦哥希望更多的人能够成为代表。

输入描述 Input Description

第一行输入两个数n和m。
以下n行每行若干个数,这些数都是不超过m的正整数。其中第i行的数表示社团i的全部成员。每行用一个0结束。

输出描述 Output Description

输出最多的能够成为代表的人数。

样例输入 Sample Input

4 4
1 2 0
1 2 0
1 2 0
1 2 3 4 0

样例输出 Sample Output

3

数据范围及提示 Data Size & Hint

各个测试点1s

数据范围
n,m<=200

 
最大流 
#include <algorithm>
#include <cstring>
#include <cstdio>

#define Max 2000
#define inf 0x7fffffff

bool vis[Max<<1];
using namespace std;
struct node
{
    int next,to,value;
}edge[Max<<1];
int head[Max<<2],Answer,deep[Max<<1],S,T,n,m,tot=1;
void add_edge(int from,int to,int v)
{
    node * w=&edge[++tot];
    w->next=head[from];
    w->to=to;
    w->value=v;
    head[from]=tot;
}
bool bfs(int s,int t)
{
    int Que[Max<<2];
    int l=0,r=0;
    Que[++r]=s;
    memset(vis,0,sizeof(vis));
    memset(deep,-1,sizeof(deep));
    deep[s]=0;
    vis[s]=1;
    while(l<r)
    {
        int tp=Que[++l];
        vis[tp]=0;
        for(int i=head[tp];i!=-1;i=edge[i].next)
        {
            if((deep[edge[i].to]==-1||deep[edge[i].to]>deep[tp]+1)&&edge[i].value)
            {
                deep[edge[i].to]=deep[tp]+1;
                if(edge[i].to==T) return 1;
                if(!vis[edge[i].to])
                {
                    Que[++r]=edge[i].to;
                    vis[edge[i].to]=1;
                }
            }
        }
    }
    return deep[t]!=-1;
}
int dfs(int now,int t,int Limit)
{
    if(now==t||Limit==0) return Limit;
    int rest=0,f;
    for(int i=head[now];i!=-1;i=edge[i].next)
    {
        if(edge[i].value&&deep[edge[i].to]==deep[now]+1&&(f=dfs(edge[i].to,t,min(edge[i].value,Limit))))
        {
            Limit-=f;
            rest+=f;
            edge[i].value-=f;
            edge[i^1].value+=f;
            if(!Limit) break;
        }
    }
    return rest;
}
void Dinic(int s,int t)
{
    while(bfs(s,t))    Answer+=dfs(s,t,inf);
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    S=0;T=n+m+1;
    for(int i=1;i<=n;++i)
    {
        add_edge(S,i,1);
        add_edge(i,S,0);
    }
    for(int i=1;i<=n;++i)
    {
        int a;
        while(scanf("%d",&a))
        {
            if(a==0)
                        break;
            else
            {
                add_edge(i,a+n,1);
                add_edge(a+n,i,0);
            }
        }
    }
    for(int i=1;i<=m;++i)
    {
        add_edge(n+i,T,1);
        add_edge(T,n+i,0);
    }
    Dinic(S,T);
    printf("%d",Answer);
    return 0;
}

 

posted @ 2017-03-12 09:16  杀猪状元  阅读(138)  评论(0编辑  收藏  举报