码迷,mamicode.com
首页 > 其他好文 > 详细

UESTC_Big Brother 2015 UESTC Training for Graph Theory<Problem G>

时间:2015-06-12 06:23:45      阅读:89      评论:0      收藏:0      [点我收藏+]

标签:

G - Big Brother

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

现在有n个囚笼,需要关押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 InputSample Output
5 5
1 1
1 2
1 3
1 4
1 5
5

 

解题报告:

这是一道二分图匹配题目,可以使用匈牙利匹配算法,也可以使用网络流来做,我在这里使用的是网络流ek算法,即建容量为1的边,创建一个虚拟开始结点,和虚拟结束结点.

跑一次最大流即可

 

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cstdio>

using namespace std;
const int maxn = 200 + 18;
const int inf = 1 << 29;
int c[maxn*2][maxn*2],f[maxn*2][maxn*2],n,m,p[maxn*2],pre[maxn*2];
queue<int>q;


int ek(int s,int t)
{
   int flow = 0;
   while(1)
    {
        memset(p,0,sizeof(p));
        pre[s] = 0;
        p[s] = inf;
        q.push(s);
        while(!q.empty())
         {
             int x = q.front();q.pop();
             for(int i = 1 ; i <= n + m + 2; ++ i)
              if (!p[i] && f[x][i] < c[x][i])
               {
                  p[i] = min(p[x],c[x][i] - f[x][i]);
                 pre[i] = x;
                 q.push(i);
              }
         }
        if (!p[t])
         break;
        flow += p[t];
        int k = t;
        while(k)
         {
             f[pre[k]][k] += p[t];
             f[k][pre[k]] -= p[t];
             k = pre[k];
         }    
    }
   return flow;
}

int main(int argc,char *argv[])
{
  scanf("%d%d",&n,&m);
  memset(c,0,sizeof(c));
  memset(f,0,sizeof(f));
  for(int i = 1 ; i <= n ; ++ i)
   {
         int s,v;
         scanf("%d",&s);
         while(s--)
          {
             scanf("%d",&v);
          c[i][v+n] = 1;
       }        
   }
  for(int i = 1 ; i <= n ; ++ i)
   c[n+m+1][i] = 1;
  for(int i = 1 ; i <= m ; ++ i)
   c[i+n][n+m+2] = 1;
  printf("%d\n",ek(n+m+1,n+m+2));
  return 0;
}

 

UESTC_Big Brother 2015 UESTC Training for Graph Theory<Problem G>

标签:

原文地址:http://www.cnblogs.com/Xiper/p/4570662.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!