网络流问题 P2763 试题库问题

题目描述

«问题描述:

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

«编程任务:

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

输入输出格式

输入格式:

 

第1行有2个正整数k和n (2 <=k<= 20, k<=n<= 1000)

k 表示题库中试题类型总数,n 表示题库中试题总数。第2 行有k 个正整数,第i 个正整数表示要选出的类型i的题数。这k个数相加就是要选出的总题数m。接下来的n行给出了题库中每个试题的类型信息。每行的第1 个正整数p表明该题可以属于p类,接着的p个数是该题所属的类型号。

 

输出格式:

 

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

 

输入输出样例

输入样例#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

说明

感谢 @PhoenixEclipse 提供spj

 

 

 

这个题目和圆桌问题是一样的,所以题解可以看圆桌问题,然后再自己写一下这个

 

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <iostream>
#include <vector>
#define inf 0x3f3f3f3f
using namespace std;
const int  maxn = 1e5 + 10;
int s, t, n, m;
struct node
{
    int from, to, cap, flow;
    node(int from=0,int to=0,int cap=0,int flow=0):from(from),to(to),cap(cap),flow(flow){}
};
vector<node>e;
vector<int>G[maxn];
int level[maxn], iter[maxn], head[maxn];
void add(int u,int v,int c)
{
    e.push_back(node(u, v, c, 0));
    e.push_back(node(v, u, 0, 0));
    int len = e.size();
    G[u].push_back(len - 2);
    G[v].push_back(len - 1);
}

void bfs(int s)
{
    memset(level, -1, sizeof(level));
    queue<int>que;
    que.push(s);
    level[s] = 0;
    while(!que.empty())
    {
        int u = que.front(); que.pop();
        for(int i=0;i<G[u].size();i++)
        {
            node &now = e[G[u][i]];
            if(level[now.to]<0&&now.cap>now.flow)
            {
                level[now.to] = level[u] + 1;
                que.push(now.to);
            }
        }
    }
}

int dfs(int u,int v,int f)
{
    if (u == v) return f;
    for(int &i=iter[u];i<G[u].size();i++)
    {
        node &now = e[G[u][i]];
        if(now.cap>now.flow&&level[now.to]>level[u])
        {
            int d = dfs(now.to, v, min(f, now.cap - now.flow));
            if(d>0)
            {
                now.flow += d;
                e[G[u][i] ^ 1].flow -= d;
                return d;
            }
        }
    }
    return 0;
}
int sum = 0;
bool dinic()
{
    int flow = 0;
    while(1)
    {
        bfs(s);
        if (level[t] < 0) return flow==sum;
        memset(iter, 0, sizeof(iter));
        int f;
        while ((f = dfs(s, t, inf)) > 0) flow += f;
    }
}

int main()
{
    cin >> m >> n;
    s = 0, t = n + m + 1;
    for (int i = 1; i <= m; i++)
    {
        int x;
        cin >> x;
        add(s, i, x);
        sum += x;
    }
    for (int i = 1; i <= n; i++) add(i + m, t, 1);
    for (int i = 1; i <= n; i++)
    {
        int p;
        cin >> p;
        while(p--)
        {
            int q; cin >> q;
            add(q, i, 1);
        }
    }
    int ans = dinic();
    if (ans == 0) printf("No Solution!\n");
    else
    {
        for(int i=1;i<=m;i++)
        {
            printf("%d:", i);
            for(int j=0;j<G[i].size();j++)
            {
                if(e[G[i][j]^1].flow==-1)
                {
                    printf(" %d", e[G[i][j]].to);
                }
            }
            printf("\n");
        }
    }
    return 0;
}

 

posted @ 2019-04-20 17:03  EchoZQN  阅读(246)  评论(1编辑  收藏  举报