建图 源点 -> 1024类人 -> 星球 -> 汇点
权 每类人数目 星球容量 星球容量
列举 0~1024 一位是1 那么和对应的星球建边
1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 #include<queue> 5 #include<math.h> 6 7 using namespace std; 8 #define inf 100000000 9 int z[2000]; 10 int vis[5000]; 11 int head[2000]; 12 int y[15]; 13 int cnt,S,T; 14 struct edg 15 { 16 int w,next,to; 17 18 }x[50000]; 19 void add(int u,int v,int w) 20 { 21 x[cnt].next=head[u]; 22 x[cnt].to=v; 23 x[cnt].w=w; 24 head[u]=cnt++; 25 } 26 int bfs() 27 { 28 memset(vis,-1,sizeof(vis)); 29 queue<int>q1; 30 q1.push(S); 31 vis[S]=0; 32 int j; 33 34 while(!q1.empty()) 35 { 36 int now=q1.front(); 37 q1.pop(); 38 for(j=head[now];j!=-1;j=x[j].next) 39 { 40 if(vis[x[j].to]<0&&x[j].w) 41 { 42 43 vis[x[j].to]=vis[now]+1; 44 q1.push(x[j].to); 45 } 46 } 47 } 48 return vis[T]!=-1; 49 } 50 int dfs(int u,int w) 51 { 52 int ans=0; 53 54 if(u==T) 55 return w; 56 int j; 57 for(j=head[u];j!=-1;j=x[j].next) 58 { 59 if(vis[x[j].to]==vis[u]+1&&x[j].w) 60 { 61 62 int b=dfs(x[j].to,min(w-ans,x[j].w)); 63 ans=ans+b; 64 x[j].w-=b; 65 x[j^1].w+=b; 66 } 67 } 68 return ans; 69 } 70 int main() 71 { 72 int n,m; 73 74 while(scanf("%d%d",&n,&m)!=EOF) 75 { 76 int i,j; 77 memset(z,0,sizeof(z)); 78 79 for(i=1;i<=n;i++) 80 { 81 int b=0; 82 83 for(j=1;j<=m;j++) 84 { 85 int a; 86 scanf("%d",&a); 87 if(a==1)b=b+(1<<(j-1)); 88 } 89 z[b]++; 90 } 91 for(i=1;i<=m;i++) 92 scanf("%d",&y[i]); 93 S=1500; 94 T=1501; //这2个点只要没用过就行 95 cnt=0; 96 memset(head,-1,sizeof(head)); 97 for(i=0;i<=1024;i++) 98 { 99 if(z[i]) 100 { 101 add(S,i,z[i]); 102 add(i,S,0); 103 } 104 } 105 106 //0 1024 人的下标 1025 1035 星球下标 107 for(i=0;i<=1024;i++) 108 { 109 if(z[i]) 110 { 111 for(j=1;j<=m;j++) 112 { 113 if(1<<(j-1)&i) 114 { 115 add(i,1024+j,y[j]); 116 add(1024+j,i,0); 117 } 118 } 119 } 120 } 121 122 for(j=1;j<=m;j++) 123 { 124 add(1024+j,T,y[j]); 125 add(T,1024+j,0); 126 } 127 128 int ans=0; 129 while(bfs()) 130 ans+=dfs(S,inf); 131 if(ans>=n) 132 printf("YES "); 133 else 134 printf("NO "); 135 } 136 137 return 0; 138 }