「网络流 24 题」试题库

来源:互联网 发布:linux卸载snmp服务 编辑:程序博客网 时间:2024/06/05 08:02
题目描述
假设一个试题库中有 n n n 道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取 m m m 道题组成试卷。并要求试卷包含指定类型的试题。试设计一个满足要求的组卷算法。
输入格式
第 1 1 1 行有 2 2 2 个正整数 k k k 和 n n n。k k k 表示题库中试题类型总数,n n n 表示题库中试题总数。第 2 2 2 行有 k k k 个正整数,第 i i i 个正整数表示要选出的类型 i i i 的题数。这 k k k 个数相加就是要选出的总题数 m m m。


接下来的 n n n 行给出了题库中每个试题的类型信息。每行的第 1 1 1 个正整数 p p p 表明该题可以属于 p p p 类,接着的 p p p 个数是该题所属的类型号。
输出格式
第 i i i 行输出 i: 后接类型 i i i 的题号。如果有多个满足要求的方案,只要输出一个方案。如果问题无解,则输出 No Solution!。
样例
样例输入


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 6 8
2: 7 9 10
3: 2 3 4 5
数据范围与提示

2≤k≤20,k≤n≤1000 2 \leq k \leq 20, k \leq n \leq 1000 2≤k≤20,k≤n≤1000


源点和类别建边,类别和试题建边,试题和汇点建边,求个最大流。

#include<stdio.h>#include<algorithm>#include<string.h>#include<queue>using namespace std;const int maxm = 10005;const int maxn = 1000005;const int INF = 1e9 + 7;struct node{int v, flow, next;}edge[maxm];int dis[maxm], dep[maxm], cur[maxm], head[maxm], f[maxm], vis[maxm], pre[maxm], a[maxm];int n, m, s, t, cnt;void init(){cnt = 0, s = 0, t = n + m + 1;memset(head, -1, sizeof(head));}void add(int u, int v, int w){edge[cnt].v = v, edge[cnt].flow = w, edge[cnt].next = head[u], head[u] = cnt++;edge[cnt].v = u, edge[cnt].flow = 0, edge[cnt].next = head[v], head[v] = cnt++;}int bfs(){queue<int>q;memset(dis, -1, sizeof(dis));dis[s] = 0;q.push(s);while (!q.empty()){int u = q.front();q.pop();for (int i = head[u];i != -1;i = edge[i].next){int v = edge[i].v;if (dis[v] == -1 && edge[i].flow){dis[v] = dis[u] + 1;q.push(v);}}}if (dis[t] == -1) return 0;return 1;}int dfs(int u, int flow){if (u == t)return flow;for (int i = cur[u];i != -1;i = edge[i].next){int v = edge[i].v;if (dis[v] == dis[u] + 1 && edge[i].flow){int d = dfs(v, min(flow, edge[i].flow));if (d > 0){edge[i].flow -= d, edge[i ^ 1].flow += d;return d;}}}return 0;}int dinic(){int ans = 0, d;while (bfs()){for (int i = s;i <= t;i++) cur[i] = head[i];while (d = dfs(s, INF))ans += d;}return ans;}int main(){int i, j, k, sum = 0, x, ans;scanf("%d%d", &n, &m);init();for (i = 1;i <= n;i++){scanf("%d", &x);sum += x;add(s, i, x);}for (i = 1;i<= m;i++){add(i + n, t, 1);scanf("%d", &k);for (j = 1;j <= k;j++){scanf("%d", &x);add(x, i + n, 1);}}ans = dinic();if (ans != sum) { printf("No Solution!\n");return 0; }for (i = 1;i <= n;i++) {printf("%d:", i);for (j = head[i];j;j = edge[j].next)if (!edge[j].flow && (j % 2 == 0))printf("%d ", edge[j].v - n);printf("\n");}return 0;}


原创粉丝点击