luogu P2417 课程 |网络流

题目描述

n个学生去p个课堂,每一个学生都有自己的课堂,并且每个学生只能去一个课堂,题目要求能够安排每一个课堂都有人吗?

输入格式

第一行是测试数据的个数,

每组测试数据的开始分别是p和n,

接着p行,每行的开始是这个课堂的学生人数m,接着m个数代表该课堂的学生编号

输出格式

如果该组数据能够这样安排就输出YES,否则输出NO。

说明/提示

对于100%的数据,\(n\le 100,m\le 20000\)


网络流求最大匹配

匈牙利算法也可以解决

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
const int inf=1<<30,N=6e4+10,M=3e5+10;
using namespace std;
int next[M],head[N],go[M],edge[M],tot;
int d[N],maxflow;
void add(int u,int v,int o){
	next[++tot]=head[u];head[u]=tot;go[tot]=v;edge[tot]=o;
	next[++tot]=head[v];head[v]=tot;go[tot]=u;edge[tot]=0;
}
int n,m,s,t;
bool bfs(){
	memset(d,0,sizeof(d));
	queue<int>q;
	q.push(s);d[s]=1;
	while(q.size()){
		int x=q.front();q.pop();
		for(int i=head[x];i;i=next[i])
		if(edge[i]&&!d[go[i]]){
			q.push(go[i]);
			d[go[i]]=d[x]+1;
			if(go[i]==t)return 1;
		}
	}
	return 0;
}
int dinic(int x,int flow){
	if(x==t)return flow;
	int rest=flow,k;
	for(int i=head[x];i&&rest;i=next[i])
	if(edge[i]&&d[go[i]]==d[x]+1){
		k=dinic(go[i],min(rest,edge[i]));
		if(!k)d[go[i]]=0;
		edge[i]-=k;
		edge[i^1]+=k;
		rest-=k;
	}
	return flow-rest;
}
int main(){
	int T;
	cin>>T;
	while(T--){
		cin>>n>>m;tot=1;
		s=0,t=n+m+1;
		swap(n,m);
		for(int i=1,p;i<=m;i++){
			scanf("%d",&p);
			add(i+n,t,1);
			for(int j=1,x;j<=p;j++){
				scanf("%d",&x);
				add(x,i+n,1);
			}
		}
		for(int i=1;i<=n;i++)add(s,i,1);
		
		int flow=0;
		maxflow=0;
		while(bfs())
		while(flow=dinic(s,inf))maxflow+=flow;
		if(maxflow==m)printf("YES\n");
		else printf("NO\n");
		memset(next,0,sizeof(next));
		memset(head,0,sizeof(head));
		memset(go,0,sizeof(go));
	}
	

}
posted @ 2019-10-05 14:24  白木偶君  阅读(119)  评论(0编辑  收藏  举报