ZOJ1140:Courses

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1140

这题求解的是二分图的最大匹配,只要匹配住可以"盖住"每门课程,即匹配数与课程数量相等,委员会就可以成立。在这里集合课程中的元素是相互独立的,学生集合中的元素也是相互独立的,因而判定这个是二分图。然后采用二分图的匈牙利算法即可。

代码如下:

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

#define MAXN 301
int p ;
int n ;

bool course[MAXN][MAXN] ;//标记课程与学生之间的关系
bool used[MAXN] ;//标记是否访问
int match[MAXN] ;//记录之间的匹配情况

bool dfs(int ) ;
int maxmatch() ;

int main()
{
	int i ;
	int j ;
	int num ;
	int t ;
	int test ;

	//freopen("in.txt" , "r" , stdin) ;

	scanf("%d" , &test) ;

	while(test--)
	{
		scanf("%d%d" ,&p , &n) ;
		memset(course , 0 , sizeof(course)) ;

		for( i = 1 ; i <= p ; i ++)
		{
			scanf("%d" , &num) ;

			for(j = 0 ; j < num ; j ++)
			{
				scanf("%d" , &t) ;
				course[i][t] = 1 ;
			}
		}

		if(maxmatch()==p)
			printf("YES\n") ;
		else
			printf("NO\n") ;
	}
    return 0;
}
//求解二分图的最大匹配
int maxmatch()
{
	int i ;
	int matchnum = 0;
	memset(match , -1 , sizeof(match));

	for(i = 1 ; i <= p ; i ++)
	{
		memset(used , 0 , sizeof(used)) ;

		if(dfs(i))
			matchnum ++ ;//累加匹配数
		if(matchnum == p)
			break ;
	}

	return matchnum ;//返回最大匹配数
}

bool dfs(int k)//dfs增广
{
	int i ;
	int temp ;

	for(i = 1 ; i <= n ; i ++)
	{
		//考虑学生集合中的所有元素,也即全部顶点
		if(course[k][i] && !used[i])//i与k邻接并且为访问过,
		{
			used[i] = 1 ;
			temp = match[i] ;
			match[i] = k ;
			//如果顶点i没匹配或者i已经匹配,但可以从match[i]出发可以找到一条增广路
			if(temp==-1 || dfs(temp))
				return 1 ;
			match[i] = temp ;
		}
	}
	return 0 ;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值