hdu 3605 Escape
题意:....
解法:很容易发现这是个匹配问题,如果直接建图的话,点的数量会达到10^5..需要进行压缩,我们发现m最大只有10个,那么表示人数的那些点可以按照和星球相连的情况进行压缩....压缩之后建图求最大流即可...
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define N 1500 6 using namespace std; 7 const int inf=(1<<30); 8 struct Edge{ 9 int u,v,c,next; 10 }edge[N*N]; 11 int head[N],dis[N],queue[N],stack[N]; 12 int s[N]; 13 int cnt; 14 void init(){ 15 cnt=0; 16 memset(head,-1,sizeof(head)); 17 memset(s,0,sizeof(s)); 18 } 19 void add(int u,int v,int c){ 20 edge[cnt].u=u;edge[cnt].v=v;edge[cnt].c=c; 21 edge[cnt].next=head[u];head[u]=cnt++; 22 } 23 int dinic(int s,int t){ 24 int ans=0; 25 while(1){ 26 int l,r,now,u,v,top; 27 memset(dis,-1,sizeof(dis)); 28 l=r=0; 29 queue[r++]=s; 30 dis[s]=0; 31 while(l<r){ 32 u=queue[l++]; 33 for(int k=head[u];k!=-1;k=edge[k].next){ 34 u=edge[k].u; 35 v=edge[k].v; 36 if(edge[k].c>0&&dis[v]==-1){ 37 dis[v]=dis[u]+1; 38 queue[r++]=v; 39 if(v==t){ 40 l=r; 41 break; 42 } 43 } 44 } 45 } 46 if(dis[t]==-1)break; 47 now=s; 48 top=0; 49 while(1){ 50 if(now!=t){ 51 int k; 52 for(k=head[now];k!=-1;k=edge[k].next){ 53 if(edge[k].c>0&&dis[edge[k].v]==dis[edge[k].u]+1)break; 54 } 55 if(k!=-1){ 56 stack[top++]=k; 57 now=edge[k].v; 58 } 59 else{ 60 if(top==0)break; 61 dis[edge[stack[--top]].v]=-1; 62 now=edge[stack[top]].u; 63 } 64 } 65 else{ 66 int flow=inf,w; 67 for(int i=0;i<top;i++){ 68 if(flow>edge[stack[i]].c){ 69 flow=edge[stack[i]].c; 70 w=i; 71 } 72 } 73 ans+=flow; 74 for(int i=0;i<top;i++){ 75 edge[stack[i]].c-=flow; 76 edge[stack[i]^1].c+=flow; 77 } 78 now=edge[stack[w]].u; 79 top=w; 80 } 81 } 82 } 83 return ans; 84 } 85 86 87 int main(){ 88 int n,m,a; 89 while(~scanf("%d%d",&n,&m)){ 90 init(); 91 int source,sink; 92 source=0; 93 sink=(1<<m)+m; 94 for(int i=1;i<=n;i++){ 95 int sum=0; 96 for(int j=0;j<m;j++){ 97 scanf("%d",&a); 98 if(a==1) 99 sum+=(1<<j); 100 } 101 s[sum]++; 102 } 103 for(int i=(1<<m);i<(1<<m)+m;i++){ 104 scanf("%d",&a); 105 add(i,sink,a); 106 add(sink,i,0); 107 } 108 for(int i=1;i<(1<<m);i++){ 109 if(s[i]>0){ 110 add(source,i,s[i]); 111 add(i,source,0); 112 for(int j=0;j<m;j++){ 113 if(i&(1<<j)){ 114 add(i,(1<<m)+j,s[i]); 115 add((1<<m)+j,i,0); 116 } 117 } 118 } 119 } 120 int ans=dinic(source,sink); 121 if(ans==n) 122 puts("YES"); 123 else 124 puts("NO"); 125 } 126 return 0; 127 }