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 }
posted @ 2012-11-21 23:11  silver__bullet  阅读(220)  评论(0编辑  收藏  举报