描述

学校的秋季运动会即将开始,为了决定参赛人员,需要统计分配比赛选手。

已知班级一共有N名学生,编号依次为1..N。

运动会一共有M项不同的比赛,编号为1..M。第i项比赛每个班需要派出m[i]名选手参加。

根据统计,编号为i的学生表示最多同时参加a[i]项比赛,并且给出他所擅长的b[i]项比赛的编号。

希望将每个学生都安排到他所擅长的比赛项目,以增加夺冠的可能性。同时又要考虑满足每项比赛对人数的要求,当然给一个学生安排的比赛项目也不能超过他愿意参加的比赛项目数量。

根据统计的结果,想知道能否有一个合适的安排,同时满足这些条件。

输入

第1行:1个整数T,表示一共有T(2≤T≤5)组数据,每组数据按如下格式给出:

第1行:2个正整数N,M。1≤N≤100,1≤M≤100。

第2行:M个整数,第i个数表示第i个项目需要的选手数量m[i]。1≤m[i]≤N。

第3..N+2行:若干整数,第i+2行表示编号为i的学生的信息。先是a[i],b[i],接下来b[i]个整数,表示其所擅长的b[i]个项目。1≤a[i]≤M

输出

第1..T行:第i行表示第i组数据能否满足要求,若能够输出"Yes",否则输出"No"。

样例输入

2
4 3
1 2 2
1 2 1 2
2 2 1 3
1 1 2
1 2 2 3
4 3
2 2 2
1 2 1 2
2 2 1 3
1 1 2
1 2 2 3
样例输出
Yes
No

提示:二分图多重匹配

我们仍然将学生看作A部,比赛项目看作B部:

接下来,根据每个学生的意愿我们将对应的A[i]和B[j]连起来。比如编号为i的学生擅长编号为j的项目,那么就连接A[i]-B[j]:

我们需要对之前的二分图进行进一步扩展。首先虚拟一个源点s和汇点t:

接下来我们根据a[i],在s和A[i]之间连接一条容量为a[i]的边。

同时将原来A[i]-B[j]直接的边都改造为从A[i]到B[j]的容量为1的边。

最后我们还要连接所有的B[j]-t。由于比赛项目B[j]最多只需要m[j]名选手参加,所以我们不妨限制B[j]-t的容量为m[j]。

这就是我们最后的网络流图。

在完成最大流后,这个网络流图的流量情况直接对应了一个分配方案:

s-A[i]:这一类边的流量表示了A[i]参加的项目数量。

A[i]-B[j]:这一类边的流量表示了A[i]是否参加项目B[j],若参加则流量为1,否则流量为0。

B[j]-t:这一类边的流量表示了参加比赛项目B[j]的选手数量。

由于流网络会自动调整去满足最大流量,所以它会自动调整每个A[i]-B[j]的流量来使得B[j]-t尽可能大。

若每个项目都能够满足人数的话,网络流会自己调整为所有B[j]-t都满流的情况。

我们只需要最后判断一下每一条B[j]-t的边是否满流,就可以知道能否满足需求。同时还可以根据A[i]-B[j]的情况,计算出每个选手所参加的比赛项目。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define MAX 205
#define MAXCF 101
#define min(a,b) (a)>(b)?(b):(a)
using namespace std;int cf[MAX][MAX];//存储图
int queue[MAX];//搜索队列
int path[MAX];//保存路径
int capacity[MAX];//流量数组,保存经过该点的最小流量
bool visited[MAX];//记录访问数组int findAugmentPath(int T)
{int i = 0, tail = 0;memset(visited, 0, sizeof(visited));queue[tail] = 1;//将源点加入队列capacity[1] = MAXCF;visited[1] = true;while (i <= tail){int u = queue[i];if (u == T)return capacity[T];//找到一条增广路径,返回该路径最小流量for (int v = 2; v <= T; v++){if (!visited[v] && cf[u][v] > 0){path[v] = u;capacity[v] = min(cf[u][v], capacity[u]);//记录路径上的最小残余流量visited[v] = true;tail++;queue[tail] = v;}}i++;}return 0;
}void modifyGraph(int T)
{int flow = capacity[T];int now = T;while (now != 1){int fa = path[now];cf[fa][now] -= flow;cf[now][fa] += flow;now = fa;}
}int main()
{int T;int N, M;int i,j;int temp;int m[MAX];int a[MAX], b[MAX];cin >> T;while (T--){cin >> N >> M;int S = 1;int E = S + N + M + 1;int result = 0;memset(cf, 0, sizeof(cf));for (i = 0; i < M; ++i){cin >> m[i];cf[S + N + i + 1][E] = m[i];result += m[i];}for (i = 0; i < N; ++i){cin >> a[i] >> b[i];cf[S][S + i + 1] = a[i];for (j = 0; j < b[i]; ++j){cin >> temp;cf[S + i + 1][S + N + temp] = 1;}}int maxFlow = 0;int delta = 0;while (delta = findAugmentPath(E)){maxFlow += delta;modifyGraph(E);}if (maxFlow == result)cout << "Yes" << endl;elsecout << "No" << endl;}return 0;
}

网络流三·二分图多重匹配相关推荐

  1. 网络流三·二分图多重匹配 HihoCoder - 1393

    网络流三·二分图多重匹配 HihoCoder - 1393 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int ma ...

  2. HDU - 3605 Escape(二分图多重匹配-网络流最大流+思维建边+状态压缩)

    题目链接:点击查看 题目大意:到世界末日了,现在人们要逃离去其他的星球,现在给出n个人以及m个星球,再给出每个人可以前往的星球,最后给出每个星球的容量,题目问最多能让多少个人逃离 题目分析:这个题读完 ...

  3. 【网络流24题】解题报告:E 、圆桌问题(最大流求二分图多重匹配)

    E .圆桌问题(最大流求二分图多重匹配)[省选/NOI- ] 可以直观的想到,二分图的左边是单位,右边是桌子 由于题目的限制 每个单位只能在一个桌子坐一个人 所以我们就把每个单位向各个桌子连一道流量为 ...

  4. 【网络流24题】No.7 试题库问题 (最大流,二分图多重匹配)

    [题意] 假设一个试题库中有 n 道试题. 每道试题都标明了所属类别. 同一道题可能有多个类别属性.现要从题库中抽取 m 道题组成试卷.并要求试卷包含指定类型的试题. 试设计一个 满足要求的组卷算法. ...

  5. POJ - 3189 Steady Cow Assignment(二分图多重匹配)

    题目链接:点击查看 题目大意:给出n只奶牛以及m个牛棚,接下来给出一个n*m的矩阵,给出每一只奶牛对于每个牛棚的喜爱度,按照降序给出,从rank1到rankm,现在问如何分配牛棚能让所有奶牛中最高的r ...

  6. poj2112(floyd+二分+二分图多重匹配)

    (感觉是一个比较基础的二分图多重匹配) 题目意思大概就是有K个挤奶点,C个奶牛,一个挤奶点能容下M个奶牛,问如果所有奶牛都被放入挤奶点时,距离最远奶牛得最短距离(距离可以经过其他点) 首先看到可以经过 ...

  7. 图论:二分图多重匹配

    使用最大流和费用流解决二分图的多重匹配 之前编辑的忘存了好气啊.. 本来打算学完二分图的乱七八糟的匹配之后再去接触网络流的,提前撞到了 之前我们说的二分图最大匹配和二分图最大权匹配有一个特点,那就是没 ...

  8. POJ - 2289 Jamie's Contact Groups(二分图多重匹配)

    题目链接:点击查看 题目大意:给出n个联系人,以及m个分组,现在需要将n个联系人分到m个分组中,需要满足让人数最多的组的人数最少,输出这个值 题目分析:因为是让最大值最小,所以肯定是要用二分解决,因为 ...

  9. [tyvj1935 Poetize3]导弹防御塔 (二分图多重匹配)

    传送门 Description Freda控制着N座可以发射导弹的防御塔.每座塔都有足够数量的导弹,但是每座塔每次只能发射一枚.在发射导弹时,导弹需要T1秒才能从防御塔中射出,而在发射导弹后,发射这枚 ...

最新文章

  1. python导入外部包_您会喜欢的10个外部Python软件包
  2. C# 串口编程 — MVVM MVVM Light 实例
  3. [hive学习翻译]Hive - Introduction
  4. WEB开发三层架构概述
  5. 深入理解Java Class文件格式
  6. 用python阐释工作量证明(proof of work)
  7. 我和乘子交替方向法admm_找到最大和交替子序列
  8. spring常见术语理解
  9. 【Python实战】使用python批量生成发票
  10. 我的AndroidManifest
  11. java8.5下载_MyEclipse 8.5 download 官方下载地址
  12. 百度谷歌雅虎搜狗提交链接入口
  13. 奔图m7100dw_奔图M7100dW驱动
  14. 俄亥俄州立大学计算机专业排名,俄亥俄州立大学计算机工程专业大学排名
  15. 随着年龄增长,我应该怎样对抗肌肉流失?
  16. Redux学习篇:关于store.subscribe()监听方法与取消监听的认识
  17. Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL ser
  18. Android实现动态贴纸,Android开发之仿微博贴纸效果实现——进阶篇
  19. Apache的虚拟主机配置和伪静态操作
  20. PCB抄板最新方法及步骤

热门文章

  1. 64匹马,8个赛道,找出前4名最少比赛多少场?
  2. 组件-Element—Badge(标记)
  3. 文件服务器文件删除记录查询,Windows server2008r2共享文件操作记录、查询服务器日志方法...
  4. 自动化控制面试问题整理
  5. 前端面试—html语义化
  6. copy con 的详细解释
  7. 职高高一计算机知识点,职高高一上半学期所有数学公式
  8. c语言输入1个数字正数负数零的个数,输入n个整数,求输入正数之和,负数之和,并统计相应正数和负数的个数,以输入0表示输入结束....
  9. 浏览器审查元素查找网页元素对应代码
  10. OGRE的安装与配置