分析:
有n个人和m个星球,给出n个人对于m个星球的态度(0为不适合居住,1为适合),再给出m个星球最大能居住多少人,要求判断这n个人能否都居住到自己喜欢的星球。
这是一道多重匹配的二分图,改改匈牙利算法就能过。(开始直接上了网络流ISAP,结果直接TLE,T ^ T)多重匹配匈牙利算法:
int N,M;
int Map[112345][12];//建立人与星球间的匹配
int Mark[12][112345];//开二维的Mark数组,记录已经匹配上的人,Mark[i][0]存放Max容量
int flag[12];
int Max[12];//每个星球的最大容量
bool DFS(int x)
{
for(int i=1;i<=M;i++)
{
if(!Map[x][i]||flag[i])
continue;
flag[i] = 1;
if( Mark[i][0]<Max[i])//若星球上还有位置
{
Mark[i][++Mark[i][0]] = x;
return true;
}
for(int j=1;j<=Mark[i][0];j++)
{//遍历一遍已经匹配过的星球,看能不能找到增广路
if(DFS(Mark[i][j]))
{
Mark[i][j] = x;
return true;
}
}
}
return false;
}
int Hungarian()
{
int ans = 0;
CLR(Mark);
for(int i=1;i<=N;i++)
{
CLR(flag);
if(!DFS(i))
{
return false;//有一个人每找到就返回false
}
}
return true;
}
- AC 代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) memset(a,0,sizeof(a))
using namespace std;
int N,M;
int Map[112345][12];
int Mark[12][112345];
int flag[12];
int Max[12];
bool DFS(int x)
{
for(int i=1;i<=M;i++)
{
if(!Map[x][i]||flag[i])
continue;
flag[i] = 1;
if( Mark[i][0]<Max[i])
{
Mark[i][++Mark[i][0]] = x;
return true;
}
for(int j=1;j<=Mark[i][0];j++)
{
if(DFS(Mark[i][j]))
{
Mark[i][j] = x;
return true;
}
}
}
return false;
}
int Hungarian()
{
int ans = 0;
CLR(Mark);
for(int i=1;i<=N;i++)
{
CLR(flag);
if(!DFS(i))
{
return false;
}
}
return true;
}
int main()
{
while(~scanf("%d%d", &N, &M))
{
CLR(Map);
for(int i=1;i<=N;i++)
{
for(int j=1;j<=M;j++)
{
scanf("%d",&Map[i][j]);
}
}
for(int i=1;i<=M;i++)
{
scanf("%d",&Max[i]);
}
int ans = Hungarian();
if(ans)
cout << "YES\n";
else cout << "NO\n";
}
return 0;
}