转载地址:http://www.cnblogs.com/Griselda/archive/2012/09/17/2689345.html
题意:
给出每个人适合住的星球信息和该星球能住多少人
第一行给出n m 代表有 n 个人 m 个星球
然后接下来n行每行m个数字 1代表适合第 i 个星球 0 代表不适合第 i 个星球
最后一行m个数表示第 i 个星球最多可以住多少个人
问是不是所有人都可以住到星球上
思路:
多重匹配
Tips:
多重匹配即 X 集合上的点对应 Y 集合上多个点 而 Y 集合上的点对应 X 中的一个点
#include <stdio.h>//感觉类似于二分匹配
#include <cstring>
#define clr(x) memset(x, 0, sizeof(x))
const int INF = 0x1f1f1f1f;
bool G[100010][15];//关系矩阵
int limit[15];//限制条件
bool vis[15];
int v1, v2;
int v[15];//记录当前星球的数目
int vv[15][100010];//模拟容器
bool find(int u)//找u的匹配星球
{
int i, j, k;
for(i = 0; i < v2; ++i) {
if(G[u][i] && !vis[i]) {
vis[i] = true;
if(v[i] < limit[i]) {//如果还有容量就加入进去
vv[i][v[i]++] = u;
return true;
}
for(j = 0; j < v[i]; ++j) {//没有容量了,就将原来容量里面的的找是否可以匹配
if(find(vv[i][j])) {
vv[i][j] = u;//如果可以匹配就将当前容量里面的替换为u
return true;
}
}
}
}
return false;
}
bool solve()
{
clr(v), clr(vv);
for(int i = 0; i < v1; ++i) {//和二分匹配思想差不多
clr(vis);
if(!find(i)) {//如果没有匹配的说明不能完全匹配
return false;
}
}
return true;
}
int main()
{
int i, j, k;
while(scanf("%d %d", &v1, &v2) != EOF)
{
clr(G);
for(i = 0; i < v1; ++i)
for(j = 0; j < v2; ++j) {
scanf("%d", &G[i][j]);
}
for(i = 0; i < v2; ++i)
scanf("%d", &limit[i]);
if(solve()) puts("YES");
else puts("NO");
}
return 0;
}