链接: http://acm.hdu.edu.cn/showproblem.php?pid=3605
题意: 有n个人(1e5),m个星球(<=10),每个人对于每个星球都有可能适应或者不适应,每个星球都有一个容量最大人口,问是否能将地球上的热都搬出去?
思路:网络流典型模型,判断满流就是了,但是注意明显按人直接建边是不可能的,所以要对人进行分类,按照他们的意愿状况,显然意愿状况一样的人建边状况是一样的,所以 添加边就可以了
源点-》人的种类(某种人的个数)-》可以去的星球(无限)-》汇点(每个星球的容量)。。。
sap玩家压线ac。。。。
代码:
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
using namespace std;
const int MAXN=1100;
int maze[MAXN][MAXN];
int gap[MAXN],dis[MAXN],pre[MAXN],cur[MAXN];
int sap(int start,int end,int nodenum){
memset(cur,0,sizeof(cur));
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
int u=pre[start]=start,maxflow=0,aug=-1;
gap[0]=nodenum;
while(dis[start]<nodenum){
loop:
for(int v=cur[u]; v<nodenum; v++)
if(maze[u][v] && dis[u]==dis[v]+1){
if(aug==-1 || aug>maze[u][v])aug=maze[u][v];
pre[v]=u;
u=cur[u]=v;
if(v==end){
maxflow+=aug;
for(u=pre[u]; v!=start; v=u,u=pre[u]){
maze[u][v]-=aug;
maze[v][u]+=aug;
}
aug=-1;
}
goto loop;
}
int mindis=nodenum-1;
for(int v=0; v<nodenum; v++)
if(maze[u][v]&&mindis>dis[v]){
cur[u]=v;
mindis=dis[v];
}
if((--gap[dis[u]])==0)break;
gap[dis[u]=mindis+1]++;
u=pre[u];
}
return maxflow;
}
int n,m,a;
int main(){
int t,cas=1;
while(scanf("%d%d",&n,&m)!=EOF){
memset(maze,0,sizeof(maze));
for(int i=0;i<n;i++){
int st=0;
for(int j=0;j<m;j++){
scanf("%d",&a);
st|=(a<<j);
}
if(st!=0) maze[0][st]++;
}
for(int i=0;i<m;i++) scanf("%d",&maze[i+(1<<m)][(1<<m)+20]);
for(int i=1;i<(1<<m);i++){
for(int j=0;j<10;j++)
if(i&(1<<j)) maze[i][j+(1<<m)]=1e6;
}
if(n==sap(0,(1<<m)+20,(1<<m)+20+1)) printf("YES
");
else printf("NO
");
}
}