LUOGU 2763 test database network flow problems 24 questions

Copyright: https: //blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/90733036

title

LUOGU 2763
Title Description

«Problem description:
Suppose there are n a test database test questions. Each test questions are marked Category. The same questions may have more than one category attributes. Extract from the current exam paper composed of m questions. And requested the papers contain the specified type of questions. Try to design a test paper algorithm requirements are met.
«Programming tasks:
For a given test paper requires calculating program to meet the requirements of the test paper.

Input and output format
input format:

Line 1 has two positive integers k and n-(2 <= k <= 20 is, k <= n-<= 1000)
k represents the total number of questions in the exam type, n represents the total number of exam questions. The second row has k a positive integer, the i-th number of questions to be a positive integer selected type i. This sum is the total number k m be the number of the selected title. The next line gives the n type of exam information for each of the questions. Each row of positive integers p 1 indicates that the problem may be of the type p, the number p is type number followed by the title belongs.

Output formats:

I-th row output "i:" Question followed by the type i. If there are a plurality of programs to meet the requirements, so long as the output of a program. If the problem is no solution, output "No Solution!".

Input Output Sample
Input Sample # 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

Output Sample # 1:

1: 1 6 8
2: 7 9 10
3: 2 3 4 5

Explanation

Thank @PhoenixEclipse provide spj

analysis

This question is a bipartite graph matching network multiple streams, and round-table issues like the fact that essentially the same .

Simple meaning of the questions:

Have n n questions, k k types. Each type is a collection of questions T i T_i . From which you choose a i a_i Road i i kind of questions, each question can only be selected once. Seeking a viable option.

Consider limiting each question with a number of selected traffic. And each question for each type and configuration points.

First, from the S S to topic i \ Text {Title} i even a flow 1 1 side, i.e., each question is selected only once;

Then from Types of i \ Text {Type} i to T T even a flow a i a_i Side, namely the need for each type of election a i a_i Road;

At last j T i \forall j \in T_i ,From 题目 i \ Text {Title} i give 类型 j \ Text {Type} j even edges, i.e., each question may be selected in the name of the appropriate type.

That is, all those programs subject to the type of edge even in full flow. If no solution flow dissatisfaction.

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10,maxm=3e4+10,maxk=25,inf=1e9;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
	x=0;
	T f=1, ch=getchar();
	while (!isdigit(ch) && ch^'-') ch=getchar();
	if (ch=='-') f=-1, ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
	x*=f;
}

template<typename T>inline void write(T x)
{
	if (!x) { putchar('0'); return ; }
	if (x<0) putchar('-'),x=-x;
	T num=0,ch[20];
	while (x) ch[++num]=x%10+48,x/=10;
	while (num) putchar(ch[num--]);
}

int ver[maxm<<1],edge[maxm<<1],Next[maxm<<1],head[maxn],len=1;
inline void add(int x,int y,int z)
{
	ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
	ver[++len]=x,edge[len]=0,Next[len]=head[y],head[y]=len;
}

int s,t;
int dist[maxn];
inline bool bfs()
{
	queue<int>q;
	memset(dist,0,sizeof(dist));
	q.push(s);dist[s]=1;
	while (!q.empty())
	{
		int x=q.front();
		q.pop();
		for (int i=head[x]; i; i=Next[i])
		{
			int y=ver[i];
			if (edge[i] && !dist[y])
			{
				dist[y]=dist[x]+1;
				if (y==t) return 1;
				q.push(y);
			}
		}
	}
	return 0;
}

inline int get(int x,int low)
{
	if (x==t) return low;
	int tmp=low;
	for (int i=head[x]; i; i=Next[i])
	{
		int y=ver[i];
		if (edge[i] && dist[y]==dist[x]+1)
		{
			int a=get(y,min(tmp,edge[i]));
			if (!a) dist[y]=0;
			edge[i]-=a;
			edge[i^1]+=a;
			if (!(tmp-=a)) break;
		}
	}
	return low-tmp;
}

int main()
{
	int k,n,sum=0,ans=0;
	read(k);read(n);
	s=0,t=n+k+1;
	for (int i=1,f; i<=k; ++i) read(f),sum+=f,add(s,i,f);
	for (int i=1,p; i<=n; ++i)
	{
		read(p);
		for (int j=1,x; j<=p; ++j) read(x),add(x,i+k,1);
	}
	for (int i=1; i<=n; ++i) add(i+k,t,1);

	while (bfs()) ans+=get(s,inf);

	if (ans!=sum) return puts("No Solution!"),0;
	for (int x=1; x<=k; ++x)
	{
		write(x),putchar(':'),putchar(' ');
		for (int i=head[x]; i; i=Next[i])
		{
			int y=ver[i];
			if (y!=s && !edge[i]) write(y-k),putchar(' ');
		}
		puts("");
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/huashuimu2003/article/details/90733036
Recommended