zoukankan      html  css  js  c++  java
  • UESTC_Big Brother 2015 UESTC Training for Graph Theory<Problem G>

    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
    ",ek(n+m+1,n+m+2));
      return 0;
    }
  • 相关阅读:
    集合类
    对象数组的练习已经对象数组的内存图
    String字符串的遍历
    About me-关于我
    工作两周年总结
    hackrf搭配gr-mixalot唤醒沉睡多年的BP机
    电视机为什么会收到邻居游戏机画面?
    分析无线遥控器信号并制作 Hack 硬件进行攻击
    使用 Arduino 和 RC Switch 逆向遥控器
    解码无线遥控器信号的 N 种方法
  • 原文地址:https://www.cnblogs.com/Xiper/p/4570662.html
Copyright © 2011-2022 走看看