博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Libre 6006 「网络流 24 题」试题库 / Luogu 2763 试题库问题 (网络流,最大流)
阅读量:5367 次
发布时间:2019-06-15

本文共 2406 字,大约阅读时间需要 8 分钟。

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

Description

问题描述:

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

编程任务:

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

Input

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

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

Output

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

Sample Input

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

Sample Output

1: 1 6 8

2: 7 9 10
3: 2 3 4 5

Http

Libre:

Luogu:

Source

网络流,最大流

解决思路

题目的描述有些问题,应该是一道题目如果选择了作为这种类型就不能选择为另外一种类型了。

对于每一种类型的要求,从源点连一条容量为要求数目的边到类型;对于每一道试题,连从对应的类型到试题容量为1的边,同时从试题到汇点连一条容量为1的边。这样就可以保证一个试题只能选择作为一种类型。然后跑最大流即可。
若最大流等于所有类型要求数量之和(即从源点出发的所有边满流),则说明有解,否则无解。
另:这里使用Dinic求解最大流,可以参考我的

代码

#include
#include
#include
#include
#include
using namespace std;const int maxN=2000;const int maxM=maxN*maxN;const int inf=2147483647;class Edge{public: int u,v,flow;};int n,m;int cnt=-1;int Head[maxN];int Next[maxM];Edge E[maxM];int depth[maxN];int cur[maxN];int Q[maxN];void Add_Edge(int u,int v,int flow);bool bfs();int dfs(int u,int flow);int main(){ memset(Head,-1,sizeof(Head)); int sum=0; scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { int num; scanf("%d",&num); sum+=num;//统计总类型要求数量 Add_Edge(0,i,num);//连边源点到类型 } for (int i=1;i<=m;i++) { int p; scanf("%d",&p); for (int j=1;j<=p;j++) { int u; scanf("%d",&u); Add_Edge(u,n+i,1);//连边类型到题目 } Add_Edge(n+i,n+m+1,1);//连边题目到汇点 } int Ans=0;//求解最大流 while (bfs()) { for (int i=0;i<=n+m+1;i++) cur[i]=Head[i]; while (int di=dfs(0,inf)) Ans+=di; } if (Ans
=n+1)&&(v<=n+m)&&(E[j].flow==0)) cout<
<<" "; } cout<
0)) { depth[v]=depth[u]+1; h++; Q[h]=v; } } } while (h!=t); if (depth[n+m+1]==-1) return 0; return 1;}int dfs(int u,int flow){ if (u==n+m+1) return flow; for (int &i=cur[u];i!=-1;i=Next[i]) { int v=E[i].v; if ((depth[v]==depth[u]+1)&&(E[i].flow>0)) { int di=dfs(v,min(flow,E[i].flow)); if (di>0) { E[i].flow-=di; E[i^1].flow+=di; return di; } } } return 0;}

转载于:https://www.cnblogs.com/SYCstudio/p/7281317.html

你可能感兴趣的文章
[Tools] 使用XP远程登录Win8系统
查看>>
【RL-TCPnet网络教程】第38章 TFTP简单文件传输基础知识
查看>>
HDU- 2265 Encoding The Diary
查看>>
socket基本概念
查看>>
[第三方]SCNetworkReachability 获取网络状态控件使用方法
查看>>
在Windows上使用putty连接一台Linux主机
查看>>
Socket常见错误
查看>>
百度地图2.0API和3.0API。你想要的百度地图的这都有
查看>>
专业词汇
查看>>
星期五的收获
查看>>
proxmox 去除订阅提示
查看>>
使用Html.EditorFor()为文本框加上maxlength,placeholder等属性
查看>>
[转]后缀数组求最长重复子串
查看>>
设计模式——外观模式详解
查看>>
MVC3 控件
查看>>
mysql (一)
查看>>
photoshop图层样式初识1
查看>>
【.NET】使用HtmlAgilityPack抓取网页数据
查看>>
typedef的使用
查看>>
基于位置的本地商铺个性化推荐
查看>>