hdu 3605 最大流sap+二进制思想(啊啊)

/*因为n非常大如果正常建边的话会超内存,每种状态的数目共2……10种状状体记录起来,源点与状态建边权值为状态数,状态与星球建边,星球与汇点建边*/

#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
#define inf 0x3fffffff
#define N  3000
struct node {
int u,v,w,next;
}bian[N*10*4];
int head[N],yong,s,t,dis[N];
void init(){
yong=0;
memset(head,-1,sizeof(head));
memset(dis,-1,sizeof(dis));
}
void addedge(int u,int v,int w) {
bian[yong].u=u;
bian[yong].v=v;
bian[yong].w=w;
bian[yong].next=head[u];
head[u]=yong++;
}
void bfs() {
int u,v,i;
queue<int>q;
q.push(t);
dis[t]=0;
while(!q.empty()) {
    u=q.front();
    q.pop();
    for(i=head[u];i!=-1;i=bian[i].next) {
        v=bian[i].v;
        if(dis[v]==-1) {
            dis[v]=dis[u]+1;
            q.push(v);
        }
    }
}
return ;
}
int ISAP() {
int sum=0;
bfs();
int  gap[N],cur[N],stac[N],top,i;
memset(gap,0,sizeof(gap));
for(i=s;i<=t;i++) {
    gap[dis[i]]++;
    cur[i]=head[i];
}
int k=s;
top=0;
while(dis[s]<t+1) {
     if(k==t) {
            int minn=inf,index;
        for(i=0;i<top;i++) {
            int e=stac[i];
            if(minn>bian[e].w) {
                minn=bian[e].w;
                index=i;
            }
        }
        for(i=0;i<top;i++) {
            int e=stac[i];
            bian[e].w-=minn;
            bian[e^1].w+=minn;
        }
        sum+=minn;
        top=index;
        k=bian[stac[top]].u;
     }
     for(i=cur[k];i!=-1;i=bian[i].next) {
       int  v=bian[i].v;
        if(bian[i].w&&dis[k]==dis[v]+1) {
            cur[k]=i;
            k=v;
            stac[top++]=i;
            break;
        }
     }
     if(i==-1) {
        int m=t+1;
        for(i=head[k];i!=-1;i=bian[i].next)
            if(m>dis[bian[i].v]&&bian[i].w) {
                m=dis[bian[i].v];
                cur[k]=i;
            }
            if(--gap[dis[k]]==0)break;
            gap[dis[k]=m+1]++;
            if(k!=s)
                k=bian[stac[--top]].u;
     }
}
return sum;
}
int main() {
     int bit[N],n,m,i,j,k,tot[N],f;
     bit[0]=1;
     for(i=1;i<10;i++)
     bit[i]=bit[i-1]*2;
     while(scanf("%d%d",&n,&m)!=EOF) {
        init();
        s=0;t=1024+m+1;
        memset(tot,0,sizeof(tot));
        for(i=1;i<=n;i++) {
            k=0;
            for(j=0;j<m;j++) {
                scanf("%d",&f);
                k=k+f*bit[j];
            }
            tot[k]++;
        }
        for(i=0;i<1024;i++) {
            if(tot[i]==0)continue;
            addedge(s,i+1,tot[i]);
            addedge(i+1,s,0);
            for(j=0;j<10;j++)
                if(i&bit[j]) {
                addedge(i+1,1024+j+1,inf);
                addedge(1024+j+1,i+1,0);
                }
        }
        for(i=0;i<m;i++) {
            scanf("%d",&f);
            addedge(1024+i+1,t,f);
            addedge(t,1024+i+1,0);
        }
        if(ISAP()==n)
            printf("YES\n");
        else
            printf("NO\n");
     }
return 0;
}

posted @ 2014-07-26 11:06  HYDhyd  阅读(159)  评论(0编辑  收藏  举报