HDU 3605 Escape 最大流,狀壓

最大流,n比較大,但是m只有10,所以對應的人的狀態最多有2^m種,因此可以對人進行歸類,那樣n的數據量就只有1024了,求最大流

g++交會超時 ,要用c++




#include <iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define MAXN 1100
#define MAXE 21000
#define INF 0x7fffffff
using namespace std;
int num[MAXN];
struct Edge{
    int to,from,cap,next;
}edge[MAXE];
int head[MAXN],cnt,n,m,src,des;
int dep[MAXN],gap[MAXN];
void init(){
    memset(head,-1,sizeof(head));
    cnt=0;
}
void addedge(int cu,int cv,int cw){
  // cout<<cu<<' '<<cv<<' '<<cw<<endl;
    edge[cnt].from=cu;edge[cnt].to=cv;edge[cnt].cap=cw;edge[cnt].next=head[cu];head[cu]=cnt++;
    edge[cnt].from=cv;edge[cnt].to=cu;edge[cnt].cap=0;edge[cnt].next=head[cv];head[cv]=cnt++;
}
int que[MAXN];
void BFS(){
    memset(dep,-1,sizeof(dep));
    memset(gap,0,sizeof(gap));
    gap[0]=1;
    int L=0,R=0;
    dep[des]=0;
    que[R++]=des;
    int u,v;
    while(L!=R){
        u=que[L++];
        L=L%MAXN;
        for(int i=head[u];i!=-1;i=edge[i].next){
            v=edge[i].to;
            if(edge[i^1].cap==0||dep[v]!=-1)
            continue;
            que[R++]=v;
            R=R%MAXN;
            ++gap[dep[v]=dep[u]+1];
        }
    }
}
int cur[MAXN],stack[MAXN];
int Sap(){
    int res=0;
    BFS();
    int top=0;
    memcpy(cur,head,sizeof(head));
    int u=src,i;
    while(dep[src]<n){
        if(u==des){
            int temp=INF,inser=n;
            for(i=0;i!=top;++i){
                if(temp>edge[stack[i]].cap){
                    temp=edge[stack[i]].cap;
                    inser=i;
                }
            }
            for(i=0;i!=top;++i){
                edge[stack[i]].cap-=temp;
                edge[stack[i]^1].cap+=temp;
            }
            res+=temp;
            top=inser;
            u=edge[stack[top]].from;
        }
        for(i=cur[u];i!=-1;i=edge[i].next)
        if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1)
        break;
        if(i!=-1){
            cur[u]=i;
            stack[top++]=i;
            u=edge[i].to;
        }else{
            if(--gap[dep[u]]==0)
            break;
            int minn=n;
            for(i=head[u];i!=-1;i=edge[i].next){
                if(edge[i].cap==0)
                continue;
                if(minn>dep[edge[i].to]){
                    minn=dep[edge[i].to];
                    cur[u]=i;
                }
            }
            ++gap[dep[u]=minn+1];
            if(u!=src)
            u=edge[stack[--top]].from;
        }
    }
    return res;
}
int main()
{
    int t,x,i,j,ans,tmp,sum;
    while(~scanf("%d%d",&n,&m)){
        init();
        memset(num,0,sizeof(num));
        for(i=1;i<=n;i++){
            tmp=0;
            for(j=1;j<=m;j++){
                scanf("%d",&x);
                tmp=(tmp<<1)+x;
            }
            num[tmp]++;
        }
        sum=n;
        src=0;
        n=1<<m;
        des=n+m+1;
        for(i=0;i<n;i++){
            if(num[i]){
                addedge(src,i+1,num[i]);
                tmp=i;
                for(j=m;j>=0;j--){
                    if(tmp&1)
                    addedge(i+1,n+j,INF);
                    tmp>>=1;
                }
            }
        }
        for(i=1;i<=m;i++){
            scanf("%d",&x);
            addedge(i+n,des,x);
        }
        n=des+1;
        ans=Sap();
        if(ans==sum)
        printf("YES\n");
        else
        printf("NO\n");
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章