洛谷 P2763 试题库问题(最大流 EK算法)
admin
2024-01-25 06:59:16
0

试题库问题

题目描述

问题描述:

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

编程任务:

对于给定的组卷要求,计算满足要求的组卷方案。

输入格式

第一行有两个正整数 kkk 和 nnn。kkk 表示题库中试题类型总数,nnn 表示题库中试题总数。

第二行有 kkk 个正整数,第 iii 个正整数表示要选出的类型 iii 的题数。这 kkk 个数相加就是要选出的总题数 mmm。

接下来的 nnn 行给出了题库中每个试题的类型信息。每行的第一个正整数 ppp 表明该题可以属于 ppp 类,接着的 ppp 个数是该题所属的类型号。

输出格式

输出共 kkk 行,第 iii 行输出 i: 后接类型 iii 的题号。
如果有多个满足要求的方案,只要输出一个方案。
如果问题无解,则输出No Solution!

样例 #1

样例输入 #1

3 15
3 3 4
2 1 2
1 3
1 3
1 3
1 3
3 1 2 3
2 2 3
2 1 3
1 2
1 2
2 1 2
2 1 3
2 1 2
1 1
3 1 2 3

样例输出 #1

1: 1 6 8
2: 7 9 10
3: 2 3 4 5

提示

2≤k≤202\leq k \leq 202≤k≤20,k≤n≤103k \leq n \leq 10^3k≤n≤103。


感谢 @PhoenixEclipse 提供 spj

1、 有n种题型(n <= 20), 有m道题(m <= 1000) 
建图 : 起点 0, 终点 n + m + 1.编号(1 ~ n) 表示题型;编号 (n + 1 ~ n + m) 表示题目;起点 0 与 (1 ~ n) 连上 n条边,边权就是这种题型需要匹配的题目(假设总数是sum);每种题型(1 ~ n)与之对应的题目,连边,边权是1;每道题(n + 1 ~ n + m), 与终点(n + m + 1) 连边,边权是1另外, 所有的反边,边权都是0
2、 图建好了,就跑最大流EK算法。 当最大流 maxflow = sum, 说明有解。
#include 
using namespace std;
const int N = 1100, M = 23000;
int n, m;	//题型, 题目总数
int a[N];
int head[N], ver[M], edge[M], Next[M];
int incf[N], pre[N];
bool vis[N];
int s, t, tot, maxflow;
vector v[N];	// v[k] 表示题型k所选择的题目void add(int x, int y, int z)
{ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot;
}bool bfs()
{memset(vis, false, sizeof vis);queue q;q.push(s); vis[s] = true;incf[s] = 0x3f3f3f3f;while(q.size()){int x = q.front(); q.pop();for(int i = head[x]; i; i = Next[i]){if(edge[i]){int y = ver[i];	if(vis[y])	continue;incf[y] = min(incf[x], edge[i]);pre[y] = i;q.push(y); vis[y] = true;if(y == t)return true;}}}return false;
}void update()
{int x = t;while(x != s){int i = pre[x];edge[i] -= incf[t];edge[i ^ 1] += incf[t];int y = ver[i ^ 1];if(1 <= y && y <= n){v[y].push_back(x - n);		// 记录没种题型对应的题目}x = y;}
}int main()
{scanf("%d%d", &n, &m);s = 0, t = n + m + 1;tot = 1;// n种题型, 点的编号 1 ~ n , 起点 s 与 这n个点连边int sum = 0;for(int i = 1; i <= n; ++i){scanf("%d", &a[i]);sum += a[i];add(0, i, a[i]); add(i, 0, 0);}int count, x;// m道题目,编号 n + 1 ~ n + m//  每道题 ---> 每种题型(编号 1 ~ m)//  题型 --> 题目  , 连上一条边(边容量是1)for(int i = 1; i <= m; ++i){scanf("%d", &count);while(count--){scanf("%d", &x);	add(x, i + n, 1);add(i + n, x, 0);}}// 每道题 --> 终点(n + m + 1) 连上一条边(边容量是1)for(int i = 1; i <= m; ++i){add(n + i, n + m + 1, 1);add(n + m + 1, n + i, 0);}while(bfs()){update();}if(maxflow < 0)printf("No Solution!\n");else{for(int i = 1; i <= n; ++i){printf("%d:", i);int size = v[i].size();for(int j = 0; j < size; ++j){printf(" %d", v[i][j]);}printf("\n");}}return 0;
}

相关内容

热门资讯

安卓手机升级苹果系统,体验全新... 你有没有想过,你的安卓手机突然间变成了苹果的忠实粉丝,想要体验一番iOS系统的魅力呢?这可不是天方夜...
安卓系统短信不通知,享受宁静 你是不是也遇到了这个问题?安卓系统短信不通知,是不是让你抓狂?别急,今天就来给你详细解析一下这个让人...
夏普电视非安卓系统,非安卓系统... 亲爱的读者们,你是否曾对夏普电视的非安卓系统感到好奇呢?今天,就让我带你一探究竟,揭开这个神秘面纱背...
安卓系统43适配软件,软件升级... 你有没有发现,你的安卓手机最近是不是有点儿“水土不服”?别急,别急,让我来给你揭秘为什么你的安卓系统...
安卓系统有车载系统吗吗,智能驾... 你有没有想过,当你坐在车里,享受着旅途的悠闲时光,手机上的安卓系统是不是也能派上用场呢?没错,我就要...
安卓8.1系统解锁方法,畅享自... 你有没有想过,你的安卓手机里隐藏着无数的小秘密?比如,解锁安卓8.1系统,就能让你的手机焕发出全新的...
安卓系统怎么打开邮件,安卓系统... 你有没有想过,每天那么多邮件,怎么才能快速打开它们呢?尤其是当你用的是安卓系统手机的时候。别急,今天...
封闭安卓系统安装软件,一步到位... 你有没有想过,为什么你的安卓手机里有些软件只能通过官方渠道安装呢?今天,就让我带你一探究竟,揭开封闭...
小米mipad升级安卓系统,解... 你有没有发现,最近小米Mipad的安卓系统升级可是个大热门呢!这不,我就迫不及待地来和你聊聊这个话题...
哪个安卓系统体验好,揭秘安卓系... 你有没有想过,手机里的安卓系统就像是个大厨,不同的版本就是不同的拿手好菜,有的让你回味无穷,有的却让...
安卓系统开发测试,全方位技术解... 你有没有想过,那个陪伴你每天刷手机、玩游戏、办公的安卓系统,是怎么从无到有,一步步成长起来的呢?今天...
安卓系统怎么查配置,轻松掌握设... 你有没有想过,你的安卓手机里藏着多少秘密?别小看这些配置信息,它们可是了解你手机性能的“小侦探”呢!...
pve下安装安卓系统,PVE环... 你有没有想过,在你的PVE服务器上安装一个安卓系统呢?听起来是不是有点酷炫?想象你的服务器不仅能够运...
安卓手机安装虹膜系统,安卓手机... 你有没有想过,你的安卓手机还能这样玩?没错,就是安装虹膜系统!听起来是不是有点酷炫?别急,让我带你一...
小米论坛原生安卓系统,深度解析... 你有没有想过,你的手机系统其实可以更加纯粹、更加原生?今天,就让我带你走进小米论坛,一探究竟,看看那...
安卓怎么装iphone系统,轻... 你是不是也和我一样,对安卓手机上的iPhone系统充满了好奇?想象那流畅的界面、强大的性能,还有那独...
模拟器系统安卓,打造移动应用开... 你有没有想过,在手机上也能体验到电脑游戏的快感?没错,这就是安卓模拟器系统的魅力所在!今天,就让我带...
安卓系统清理系统更新包,提升运... 手机里的安卓系统是不是越来越慢了?别急,今天就来给你支个招,让你的安卓手机焕然一新!那就是——清理系...
酷开系统是安卓系统不,深度解析... 亲爱的读者,你是否曾好奇过,那些在我们手机、电视上运行得风生水起的操作系统,它们之间究竟有何不同?今...
小说系统类游戏安卓,安卓世界逆... 你有没有想过,在手机上玩一款能让你瞬间穿越到小说世界的游戏?想象你不再是旁观者,而是故事的主角,那种...