HDU 3605 Escape(多重匹配)

Escape

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 11950    Accepted Submission(s): 2919


Problem Description
2012 If this is the end of the world how to do? I do not know how. But now scientists have found that some stars, who can live, but some people do not fit to live some of the planet. Now scientists want your help, is to determine what all of people can live in these planets.
 

Input
More set of test data, the beginning of each data is n (1 <= n <= 100000), m (1 <= m <= 10) n indicate there n people on the earth, m representatives m planet, planet and people labels are from 0. Here are n lines, each line represents a suitable living conditions of people, each row has m digits, the ith digits is 1, said that a person is fit to live in the ith-planet, or is 0 for this person is not suitable for living in the ith planet.
The last line has m digits, the ith digit ai indicates the ith planet can contain ai people most..
0 <= ai <= 100000
 

Output
Determine whether all people can live up to these stars
If you can output YES, otherwise output NO.
 

Sample Input
 
 
1 1
1
1
2 2
1 0
1 0
1 1
 

Sample Output
 
 
YES
NO

问题描述
2012如果这是世界末日该怎么办?我不知道怎么。但是现在科学家们已经发现有些恒星可以生存,但有些人不适合生活在这个星球上。现在科学家需要你的帮助,是要确定所有人能够在这些行星中生活。
输入
更多的测试数据集,每个数据的开始是n(1 <= n <= 100000),m(1 <= m <= 10)n表示地球上有n个人,m代表行星,行星和人标签是从0开始的。这里有n行,每行代表一个合适的人的生活条件,每行有m位,第i位数是1,表示一个人适合生活在第i行星,或者是0这个人不适合生活在第i个星球上。
最后一行有m位,第i位数字表示第i行星最多可以包含ai人。
0 <= ai <= 100000
输出
确定是否所有人都能生活在这些星球
如果可以输出YES,否则输出NO。

     第一次了解到多重匹配,但是搜题解为什么好多人用网络流,最大流写呢,还都是140、150多行的代码。。。大概因为写起来爽吧!刚了解多重匹配,还得在了解网络流,有点无奈。

多重匹配和二分图的最大匹配很相似的,稍作加工,思想都一样。函数dfs()中就是核心代码。

可以当多重分配的模板了,比较好,连输入都函数化了,以后可以多多尝试这种代码风格。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,m;
int mat[15][100005];//保存我们安排的匹配,数组的行列刚好与p数组相反 
int vnum[15];//vnum[i]:i当前已匹配的人数 
int p[100005][15];//原始关系匹配图,谁可以和谁匹配;p[i][j]:i可以与j匹配,可以看出是一对多的 
int vis[15];//标记 
int w[15];//w[i]:i最多匹配的人数 
void input()//输入 
{
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			scanf("%d",&p[i][j]);//每个人可以匹配的行星 
		}
	}
	for(int i=0;i<m;i++)
		scanf("%d",&w[i]);//每个行星最多容纳的人数 
	return;
}
int dfs(int v)
{
	for(int i=0;i<m;i++)
	{
		if(p[v][i]&&!vis[i])
		{
			vis[i]=1;
			if(vnum[i]<w[i])//当前行星容纳的人数小于最大值,还可以匹配 
			{
				mat[i][vnum[i]++]=v;//第vum[i]++个是v 
				return 1;
			}
			else
			{
				for(int j=0;j<vnum[i];j++)//否则让别人去另一个行星 
				{
					if(dfs(mat[i][j]))
					{
						mat[i][j]=v;
						return 1;
					}
				}
			}
		}
	}
	return 0;
}
void judge()
{
	for(int i=0;i<n;i++)
	{
		memset(vis,0,sizeof(vis));
		if(!dfs(i))//有人不能被匹配到行星 
		{
			printf("NO\n");
			return;
		}
	}
	printf("YES\n");
	return;
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		input();
		memset(vnum,0,sizeof(vnum));
		judge();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值