zoukankan      html  css  js  c++  java
  • P2763 试题库问题

    Link

    第一道自己做出来网络流24题。那个飞行员配对方案不算,自己还没调出来呢嘤嘤嘤

    题目描述

    问题描述:

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

    编程任务:

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

    输入格式

    第一行有两个正整数 (k)(n)(k) 表示题库中试题类型总数,(n) 表示题库中试题总数。

    第二行有 (k) 个正整数,第 (i) 个正整数表示要选出的类型 (i) 的题数。这 (k) 个数相加就是要选出的总题数 (m)

    接下来的 (n) 行给出了题库中每个试题的类型信息。每行的第一个正整数 (p) 表明该题可以属于 (p) 类,接着的 (p) 个数是该题所属的类型号。

    输出格式

    输出共 (k) 行,第 (i) 行输出 i: 后接类型 (i) 的题号。
    如果有多个满足要求的方案,只要输出一个方案。
    如果问题无解,则输出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
    

    说明/提示

    (2leq k leq 20)(k leq n leq 10^3)

    题解

    既然是网络流24题,那么就主要讲讲建模吧。

    这道题其实求的是最大流,怎么说呢?

    每道题只能选一次,所以我们从源点向他连一条容量为 (1) 的边。

    我们每种类型,选的是有限制的,那我们可以从每种类型向汇点连一条容量为 (w[i])(w[i]),表示这种类型的题要选几道)的边

    然后向每道题向他所属的类型连一条容量为 (1) 的边,表示我们这种类型可以选这道题一次。

    求出的最大流就是我们最多可以组的题目的数量。

    无解的情况就是 (最大流 < 要选的题的总数的时候)

    输出方案的话,就在残留网络中找边权为 (0) 的边,边的起点和终点就是我们的一组配对。

    开个 (vector) 存一下就可以。

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int inf = 2147483647;
    const int N = 1010;
    int k,n,ans,sum,s,t,x,num,tot = 1;
    int head[N],dep[N],w[N];
    vector<int> v[N];
    struct node
    {
    	int to,net,w;
    }e[100010];
    inline int read()
    {
    	int s = 0,w = 1; char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
    	return s * w;
    }
    void add(int x,int y,int z)
    {
    	e[++tot].w = z;
    	e[tot].to = y;
    	e[tot].net = head[x];
    	head[x] = tot;
    }
    bool bfs()
    {
    	queue<int> q;
    	memset(dep,0,sizeof(dep));
    	q.push(s); dep[s] = 1;
    	while(!q.empty())
    	{
    		int x = q.front(); q.pop();
    		for(int i = head[x]; i; i = e[i].net)
    		{
    			int to = e[i].to;
    			if(e[i].w && !dep[to])
    			{
    				q.push(to);
    				dep[to] = dep[x] + 1;
    				if(to == t) return 1;
    			}
    		}
    	}
    	return 0;
    }
    int dinic(int x,int flow)//dinic模板
    {
    	if(x == t) return flow;
    	int rest = flow;
    	for(int i = head[x]; i && rest; i = e[i].net)
    	{
    		int to = e[i].to;
    		if(e[i].w && dep[to] == dep[x] + 1)
    		{
    			int k = dinic(to,min(rest,e[i].w));
    			if(!k) dep[to] = 0;
    			e[i].w -= k;
    			e[i^1].w += k;
    			rest -= k;
    		}
    	}
    	return flow - rest;
    }
    void debug()
    {
    	printf("-------->
    ");
    	for(int i = 0; i <= n+k; i++)
    	{
    		for(int j = head[i]; j; j = e[j].net)
    		{
    			int to = e[j].to;
    			printf("%d %d %d
    ",i,to,e[j].w);
    		}
    	}
    }
    int main()
    {
    	k = read(); n = read();
    	s = 0, t = k+n+1;
    	for(int i = 1; i <= k; i++)
    	{
    		w[i] = read(); sum += w[i];
    		add(n+i,t,w[i]); add(t,n+i,0);//由每种类型向汇点连一条容量为 w[i] 的边
    	}
    	for(int i = 1; i <= n; i++)
    	{
    		num = read();
    		for(int j = 1; j <= num; j++)
    		{
    			x = read();
    			add(i,n+x,1); add(n+x,i,0);//把每道题以及他所属的类型连边
    		}
    	}
    	for(int i = 1; i <= n; i++)
    	{
    		add(s,i,1); add(i,s,0);//再有源点向每道题连一条边
    	}
    //	debug();
    	int flow = 0;
    	while(bfs())
    	{
    		while(flow = dinic(s,inf)) ans += flow;
    	}
    	if(ans < sum)//无解的情况
    	{
    		printf("No Solution!
    ");
    		return 0;
    	}
    	for(int i = 1; i <= n; i++)
    	{
    		for(int j = head[i]; j; j = e[j].net)
    		{
    			int to = e[j].to;
    			if(e[j].w == 0) v[to].push_back(i);
    		}
    	}
    	for(int i = n+1; i <= n+k; i++)
    	{
    		printf("%d: ",i-n);
    		for(int j = 0; j < min(w[i-n],(int)v[i].size()); j++)
    		{
    			printf("%d ",v[i][j]);
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    C# 汉字转拼音(转)
    检测Sql Server服务器SQL语句执行情况
    查看sql执行的情况
    Sql Server简单加密与解密 【转】
    细说SQL Server中的加密【转】
    asp.net发布到IIS中出现错误:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”
    HTTPS那些事(三)攻击实例与防御
    HTTPS那些事(二)SSL证书
    HTTPS那些事(一)HTTPS原理
    achartengine(Google给android提供的画图工具包)的介绍和使用
  • 原文地址:https://www.cnblogs.com/genshy/p/13727197.html
Copyright © 2011-2022 走看看