网络流24题—— 试题库问题
来源:互联网 发布:域名运营商查询 编辑:程序博客网 时间:2024/05/20 09:43
题目描述
假设一个试题库中有n道试题。每道试题都标明了所属类别。同一道题可能有多个类别
属性。现要从题库中抽取m 道题组成试卷。并要求试卷包含指定类型的试题。试设计一个
满足要求的组卷算法。
编程任务:
对于给定的组卷要求,计算满足要求的组卷方案。
输入格式
由文件input.txt提供输入数据。文件第1行有2个正整数k和n (2 <=k<= 20, k<=n<= 1000)
k 表示题库中试题类型总数,n 表示题库中试题总数。第2 行有k 个正整数,第i 个正整数
表示要选出的类型i 的题数。这k个数相加就是要选出的总题数m。接下来的n行给出了题
库中每个试题的类型信息。每行的第1 个正整数p表明该题可以属于p类,接着的p个数是
该题所属的类型号。
输出格式
程序运行结束时,将组卷方案输出到文件output.txt 中。文件第i 行输出 “i:”后接类
型i的题号。如果有多个满足要求的方案,只要输出1 个方案。如果问题无解,则输出“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
这道题,应该算是二分图匹配的变式吧?
先来试试二分图匹配的建图方法!
看做两个集合,取名无力的我选择让他们一个叫A集,一个叫B集!
A集表示需要的类型,B集表示题目
酱紫,就变成了二分图匹配的问题啦!
从A集出发有很多很多条边到B集。
用最原始的方法
假设类型一需要3道题,那么我们可以看做存在三个类型一,然后每个类型一需要一道题
对于所有的类型需要的题数都同理操作,就是正正经经的二分图匹配问题啦!
具体说说这个怎么建图:
假设,类型i需要x[i]道题目
首先,……超级源点….超级汇点
然后,把x[i]个类型i和超级源点连起来,令其容量为1
再然后,把题目和超级汇点连起来,令容量为1
接着(然后用的太多了,换个词),把类型和题目按照题目连接起来
最后,跑dinic
模仿金星老师:完美~
不过我没写过,大概会TLE?唔,无聊的时候可以写写(捂脸)
来稍微改动改动!体现网络流的优越性(雾)
咱们来把类型i的x[i]个点合并起来,令超级源点到类型i所代表的点的容量为i
然后,就跑dinic
和之前的某道题一样哟,某条边的flow==1就代表被匹配到了!
唔,顺便说一句。这样跑出来的最大流的值如果比需要的题目数量还少,就代表木有成功咯,需要输出”No Solution!”
然后就没有然后啦!和以前一样搞就可以了的说~
唔,温馨提示:注意数据范围
因为我RE了!(捂脸)
#include<cstdio>#include<vector>#include<cstring>#include<queue>#define INF 1e8using namespace std;const int maxn=1505;int n,m,s,t;struct Edge{int from,to,cap,flow;};vector<Edge>edges(20000);vector<int>G[maxn];int d[maxn];bool vis[maxn];int k;void AddEdge(int from,int to,int cap){ edges.push_back((Edge){from,to,cap,0}); edges.push_back((Edge){to,from,0,0}); k=edges.size(); G[from].push_back(k-2); G[to].push_back(k-1);}int DFS(int x,int a){ int flow=0,f; if(x==t || a==0) return a; for(int i=0;i<G[x].size();i++){ Edge& e=edges[G[x][i]]; if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow)))>0){ e.flow+=f; edges[G[x][i]^1].flow-=f; a-=f; flow+=f; if(a==0) break; } } return flow;}bool BFS(){ queue<int>q; memset(vis,0,sizeof(vis)); d[s]=1;vis[s]=true;q.push(s); while(!q.empty()){ int x=q.front();q.pop(); for(int i=0;i<G[x].size();i++){ Edge& e=edges[G[x][i]]; if(!vis[e.to] && e.cap>e.flow){ d[e.to]=d[x]+1; vis[e.to]=true; q.push(e.to); } } } return vis[t];}int dinic(){ int flow=0; while(BFS()) flow+=DFS(s,INF); return flow;}int main(){ int sum=0; scanf("%d%d",&n,&m); s=0;t=n+m+1; for(int c,i=1;i<=n;i++){ scanf("%d",&c); AddEdge(s,i,c); sum+=c; } for(int a,k,i=1;i<=m;i++){ scanf("%d",&k); for(int j=1;j<=k;j++){ scanf("%d",&a); AddEdge(a,i+n,1); } } for(int i=n+1;i<=m;i++) AddEdge(i,t,1); if(dinic()!=sum){puts("No Solution!");} else{ for(int i=1;i<=n;i++){ printf("%d:",i); for(int j=0;j<G[i].size();j++){ Edge e=edges[G[i][j]]; if(e.to!=t && e.flow==1){ printf(" %d",e.to-n); } } printf("\n"); } } return 0;}
- 网络流24题—— 试题库问题
- [网络流24题 #7]试题库问题
- 【网络流24题】试题库问题
- 网络流24题之试题库问题
- 【网络流24题】试题库问题
- 网络流24题7. 试题库问题
- [网络流24题]试题库问题
- 网络流24题:试题库问题
- 线性规划与网络流24——试题库问题
- 线性规划与网络流24题 07试题库问题
- 网络流与线性规划24题07试题库问题
- kyeremal-网络流24题T7-试题库问题
- 试题库问题[网络流24题之7]
- 【线性规划与网络流24题 7】试题库问题
- 线性规划与网络流24题之 试题库问题
- 网络流24题之T7 试题库问题
- 试题库问题(网络24题,五)
- 网络流二十四题之七 —— 试题库问题(DATA)
- c++中的类型转换
- python计算运行时间(转)
- 1748. The Most Complex Number/LG的数学计划~~~持续更新ing(反素数求解)
- Java泛型通配符
- The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDat
- 网络流24题—— 试题库问题
- ZooKeeper集群-搭建指南
- Fresco基本使用
- 欢迎使用CSDN-markdown编辑器
- libgdx绘制线段
- LG 的数学计划 ---- 第四步 快速幂
- [LeetCode] 287. Find the Duplicate Number
- JS中slice,splice,split的区别
- Nginx安装