本题可以用最大流也可以用最大匹配(本质一样),用dinic最大流好建图,但码量大,匈牙利码量小,建图费点劲。

最大流:依旧是设一个源点一个汇点,对于每一个种类,连一条到汇点的边,capacity为需要的量,对于每一个试题,从源点连一条capacity为1的边到他,从他对每一个其所属的编号种类连一条capacity为1的边,求最大流即可,再找出最小割即可

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define lowbit(x) ((x)&(-x))
  4. typedef long long LL;
  5.  
  6. const int maxm = 1e5+;
  7. const int maxn = 1e3+;
  8. const int INF = 0x3f3f3f3f;
  9.  
  10. struct edge{
  11. int u, v, cap, flow, nex;
  12. } edges[maxm];
  13.  
  14. int head[maxm], cur[maxm], cnt, level[maxn], capacity[];
  15. vector<int> ans[];
  16.  
  17. void init() {
  18. memset(head, -, sizeof(head));
  19. }
  20.  
  21. void addedge(int u, int v, int cap) {
  22. edges[cnt] = edge{u, v, cap, , head[u]};
  23. head[u] = cnt++;
  24. }
  25.  
  26. void bfs(int s) {
  27. memset(level, -, sizeof(level));
  28. queue<int> q;
  29. level[s] = ;
  30. q.push(s);
  31. while(!q.empty()) {
  32. int u = q.front();
  33. q.pop();
  34. for(int i = head[u]; i != -; i = edges[i].nex) {
  35. edge& now = edges[i];
  36. if(now.cap > now.flow && level[now.v] < ) {
  37. level[now.v] = level[u] + ;
  38. q.push(now.v);
  39. }
  40. }
  41. }
  42. }
  43.  
  44. int dfs(int u, int t, int f) {
  45. if(u == t) return f;
  46. for(int& i = cur[u]; i != -; i = edges[i].nex) {
  47. edge& now = edges[i];
  48. if(now.cap > now.flow && level[u] < level[now.v]) {
  49. int d = dfs(now.v, t, min(f, now.cap - now.flow));
  50. if(d > ) {
  51. now.flow += d;
  52. edges[i^].flow -= d;
  53. return d;
  54. }
  55.  
  56. }
  57. }
  58. return ;
  59. }
  60.  
  61. int dinic(int s, int t) {
  62. int maxflow = ;
  63. for(;;) {
  64. bfs(s);
  65. if(level[t] < ) break;
  66. memcpy(cur, head, sizeof(head));
  67. int f;
  68. while((f = dfs(s, t, INF)) > )
  69. maxflow += f;
  70. }
  71. return maxflow;
  72. }
  73.  
  74. void run_case() {
  75. int k, n, p, u, sum = ;
  76. init();
  77. cin >> k >> n;
  78. int s = , t = n+k+;
  79. for(int i = ; i <= k; ++i) {
  80. cin >> capacity[i];
  81. sum += capacity[i];
  82. addedge(n+i, t, capacity[i]), addedge(t, n+i, );
  83. }
  84. for(int i = ; i <= n; ++i) {
  85. cin >> p;
  86. addedge(s, i, ), addedge(i, s, );
  87. while(p--) {
  88. cin >> u;
  89. addedge(i, u+n, ), addedge(u+n, i, );
  90. }
  91. }
  92. if(dinic(s, t) != sum) {cout << "No Solution!"; return;}
  93. for(int i = ; i <= n; ++i) {
  94. for(int j = head[i]; j != -; j = edges[j].nex) {
  95. if(edges[j].flow) {
  96. ans[edges[j].v - n].push_back(i);
  97. break;
  98. }
  99. }
  100. }
  101. for(int i = ; i <= k; ++i) {
  102. cout << i << ":";
  103. for(auto j : ans[i])
  104. cout << " " << j;
  105. cout << "\n";
  106. }
  107. }
  108.  
  109. int main() {
  110. ios::sync_with_stdio(false), cin.tie();
  111. run_case();
  112. //cout.flush();
  113. return ;
  114. }

Dinic

匈牙利:对于每一个种类都连一条边到其所属的试卷,求最大匹配即可(无代码)

luogu P2763 试题库问题的更多相关文章

  1. 【题解】Luogu P2763 试题库问题

    原题传送门 这题很简单啊 从源点向k类题目分别连流量为所需数量的边 从每道题向汇点连一条流量为1的边(每题只能用1次) 从类型向对应的题目连一条流量为1的边 跑一遍最大流 如果最大流小于所需题目数量, ...

  2. P2763 试题库问题(dinic)

    P2763 试题库问题 dinic 搞个虚拟源点和汇点,瞎建建边就好辣. 偷张图↓↓ 如果没满流就是无解辣 输出方案咋办呢? 枚举每种类型,蓝后枚举它们的边 如果该边被使用了(通过判断反向边的流量), ...

  3. Libre 6006 「网络流 24 题」试题库 / Luogu 2763 试题库问题 (网络流,最大流)

    Libre 6006 「网络流 24 题」试题库 / Luogu 2763 试题库问题 (网络流,最大流) Description 问题描述: 假设一个试题库中有n道试题.每道试题都标明了所属类别.同 ...

  4. 【题解】 P2763 试题库问题(网络流)

    P2763 试题库问题 考虑一个试题要被加入进答案的集合有什么条件? 是某种类型 只算作一次 就这两种且的限制,所以我们用串联的方式连接"类型点"和"作用点". ...

  5. 网络流问题 P2763 试题库问题

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

  6. 洛谷 P2763 试题库问题(网络流24题之一)

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

  7. [洛谷P2763]试题库问题

    题目大意:有 $k$ 种类型和 $n$ 个题目,每个题目会适应部分类型,第$i$个类型需要$s_i$的题,一道题只能满足一种类型,现要求出满足所有类型的题目的方案 题解:看到匹配,想到网络流,源点向试 ...

  8. 洛谷P2763 试题库问题(最大流)

    题意 $n$道试题,每道题有多种类别属性 抽取$m$道题组成试卷,要求包含指定的类型 输出方案 Sol 又是一道zz网络流 我的构图长这样,$k_i$表示第$i$道试题需要的数量 #include&l ...

  9. P2763 试题库问题 (网络流 最大流)

    传送门 解题思路 比较简单的网络流,建图还是比较好想的.让源点向试题连流量为1的边,试题向所属类型连流量为1的边,类型向汇点连流量为需要此类试题的边.直接跑最大流,输出答案时找到那些满流的边所对的点. ...

随机推荐

  1. 吴裕雄--天生自然Numpy库学习笔记:NumPy 统计函数

    NumPy 提供了很多统计函数,用于从数组中查找最小元素,最大元素,百分位标准差和方差等. numpy.amin() 用于计算数组中的元素沿指定轴的最小值. numpy.amax() 用于计算数组中的 ...

  2. 炼金术(2): 为什么要用issue管理软件

    在项目开发中,存在的无数的任务分解,问题管理,流程跟踪.因为直接说话或者直接在IM里喊话是很容易的,所以在一个还没有习惯使用issue管理软件的团队中,直接说话或者直接在IM里AT,就在某些时候变成了 ...

  3. 安装Ubuntu后的一些配置

    Ubuntu安装的一些配置 搜狗拼音的安装 卸载ibus和它的配置, 卸载顶部面板的键盘指示 sudo apt remove ibus sudo apt purge ibus sudo apt rem ...

  4. ArrayQueue(队列)

    code1: #include <stdio.h> #include <conio.h> #include <stdlib.h> #define MAXSIZE 6 ...

  5. Trie学习总结

    Trie树学习总结 字典树,又称前缀树,是用于快速处理字符串的问题,能做到快速查找到一些字符串上的信息. 另外,Trie树在实现高效的同时,会损耗更多的空间,所以Trie是一种以空间换时间的算法. T ...

  6. 使用pyinstaller打包.py程序

    使用pyinstaller打包.py程序 例如打包D:/Desktop 目录下的 filename.py 文件 打开 cmd 将目录切换至 D:/Desktop 输入命令 pyinstaller -F ...

  7. Qt5.5 使用smtp发邮件的各种坑

    本人刚开始学习C++,用的是Qt5.5的IED,经过了两天的学习和查找资料,终于成功发了第一封邮件.以163邮箱为例,简单总结一下. 1.设置邮箱 这一步比较关键,要开通smtp服务,在开通的过程中会 ...

  8. 【PAT甲级】1035 Password (20 分)

    题意: 输入一个正整数N(<=1000),接着输入N行数据,每行包括一个ID和一个密码,长度不超过10的字符串,如果有歧义字符就将其修改.输出修改过多少组密码并按输入顺序输出ID和修改后的密码, ...

  9. windows通过zip安装mysql5.7.26的一个坑

    需要将my.ini的 红框的/不能写成\ 注意编码格式问题 然后 mysqld --initialize-insecure mysqld --install net start mysql

  10. Java-用星号打印菱形

    打印如图所示菱形9行9列(提示可以将菱形分成上下两个三角形,分析每行空格数和星号个数的关系) 代码如下: package com.homework.lhh; public class Ex20 { p ...