NKOI 1942 试题库问

【线性规划与网络流24题 7】试题库问

Time Limit:10000MS  Memory Limit:65536K
Total Submit:28 Accepted:8 
Case Time Limit:1000MS

Description

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

由于本OJ无Special Judge , 所以只需要判断是否存在满足要求的组卷方案

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

一行,包含一个字符串 如果存在,输出"YES"(不包含引号), 如果不存在,输出"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

YES

Source

感谢 Wo_ai_WangYuan 修改题目并放上数据


建图:源点和每道题连容量为1的边,每道题与其所属的类型连容量为1的边,每个类型与汇点连容量为所需量的边

跑最大流,如果maxflow==sum(sum为所需的试题数)输出yes

#include<cstdio>
#include<iostream>
using namespace std;
const int maxn=1005,inf=1e9;
inline void _read(int &x){
    char t=getchar();bool sign=true;
    while(t<'0'||t>'9')
    {if(t=='-')sign=false;t=getchar();}
    for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
    if(!sign)x=-x;
}
int n,k,g[maxn][maxn+25],op,ed,maxflow;
int vd[2005],dis[2005];
int dfs(int u,int flow){      
    if(u==ed)return flow;      
    int v,temp,delta=0;      
    for(v=1;v<=ed;v++)      
        if(g[u][v]&&dis[u]==dis[v]+1){      
            temp=dfs(v,min(flow-delta,g[u][v]));      
            g[u][v]-=temp;      
            g[v][u]+=temp;      
            delta+=temp;      
            if(delta==flow||dis[op]>=ed)return delta;      
        }      
    if(dis[op]>=ed)return delta;      
    vd[dis[u]]--;      
    if(vd[dis[u]]==0)dis[op]=ed;      
    dis[u]++;      
    vd[dis[u]]++;      
    return delta;      
}
int main(){
	cin>>k>>n;
	int i,j,x,m,sum=0;
	op=n+k+1,ed=op+1;
	for(i=1;i<=k;i++){
		_read(x);
		g[i+n][ed]=x;
		sum+=x; 
	}
	for(i=1;i<=n;i++){
		_read(m);
		g[op][i]=1;
		while(m--){
			_read(x);
			g[i][x+n]=1;
		}
	}
	while(dis[op]<ed)maxflow+=dfs(op,inf);
	if(maxflow==sum)puts("YES");
	else puts("No Solution!");
}


评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值