HDU 3605 Escape (最大流)

Escape

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Description
2012 If this is the end of the world how to do? I do not know how. But now scientists have found that some stars, who can live, but some people do not fit to live some of the planet. Now scientists want your help, is to determine what all of people can live in these planets.
 

 

Input
More set of test data, the beginning of each data is n (1 <= n <= 100000), m (1 <= m <= 10) n indicate there n people on the earth, m representatives m planet, planet and people labels are from 0. Here are n lines, each line represents a suitable living conditions of people, each row has m digits, the ith digits is 1, said that a person is fit to live in the ith-planet, or is 0 for this person is not suitable for living in the ith planet.
The last line has m digits, the ith digit ai indicates the ith planet can contain ai people most..
0 <= ai <= 100000
 

 

Output
Determine whether all people can live up to these stars
If you can output YES, otherwise output NO.
 

 

Sample Input
1 1
1
1
 
2 2
1 0
1 0
1 1
 

 

Sample Output
YES
NO
 
 
分析
很裸的最大流,但是点特别多,我用SAP超时了。
我们可以看到有m个0和1,因此可以用状态压缩,将一个人的信息压缩成一个二进制数,这样就只有1024+m+2的点了
 
但是还有特别坑的,还好网上看到了学长的题解,HDU要将G++改为C++才能AC,不然读数据就会TLE
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
//****************************************************
//最大流模板  SAP算法
//邻接表形式
//******************************************************
const int MAXN = 100000+110;//点数的最大值
const int MAXM = 4000110;//边数的最大值
const int INF = 0x3f3f3f3f;

struct Node
{
    int from,to,next;
    int cap;
}edge[MAXM];
int tol;
int head[MAXN];
int dep[MAXN];
int gap[MAXN];//gap[x]=y :说明残留网络中dep[i]==x的个数为y

int n;//n是总的点的个数,包括源点和汇点

void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}

void addedge(int u,int v,int w)
{
    edge[tol].from=u;
    edge[tol].to=v;
    edge[tol].cap=w;
    edge[tol].next=head[u];
    head[u]=tol++;
    edge[tol].from=v;
    edge[tol].to=u;
    edge[tol].cap=0;
    edge[tol].next=head[v];
    head[v]=tol++;
}
void BFS(int start,int end)
{
    memset(dep,-1,sizeof(dep));
    memset(gap,0,sizeof(gap));
    gap[0]=1;
    int que[MAXN];
    int front,rear;
    front=rear=0;
    dep[end]=0;
    que[rear++]=end;
    while(front!=rear)
    {
        int u=que[front++];
        if(front==MAXN)front=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dep[v]!=-1)continue;
            que[rear++]=v;
            if(rear==MAXN)rear=0;
            dep[v]=dep[u]+1;
            ++gap[dep[v]];
        }
    }
}
int SAP(int start,int end)
{
    int res=0;
    BFS(start,end);
    int cur[MAXN];
    int S[MAXN];
    int top=0;
    memcpy(cur,head,sizeof(head));
    int u=start;
    int i;
    while(dep[start]<n)
    {
        if(u==end)
        {
            int temp=INF;
            int inser;
            for(i=0;i<top;i++)
               if(temp>edge[S[i]].cap)
               {
                   temp=edge[S[i]].cap;
                   inser=i;
               }
            for(i=0;i<top;i++)
            {
                edge[S[i]].cap-=temp;
                edge[S[i]^1].cap+=temp;
            }
            res+=temp;
            top=inser;
            u=edge[S[top]].from;
        }
        if(u!=end&&gap[dep[u]-1]==0)//出现断层,无增广路
          break;
        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;
            S[top++]=i;
            u=edge[i].to;
        }
        else
        {
            int min=n;
            for(i=head[u];i!=-1;i=edge[i].next)
            {
                if(edge[i].cap==0)continue;
                if(min>dep[edge[i].to])
                {
                    min=dep[edge[i].to];
                    cur[u]=i;
                }
            }
            --gap[dep[u]];
            dep[u]=min+1;
            ++gap[dep[u]];
            if(u!=start)u=edge[S[--top]].from;
        }
    }
    return res;
}

int num[1025];
int bit[11];

int main()
{
    int N,M;
    int v;
    bit[0]=1;
    for(int i=1;i<=10;i++) bit[i]=bit[i-1]*2;
    while(scanf("%d%d",&N,&M)!=EOF){
        if(N==0||M==0) break;
        int st,ed;
        init();
        st=0,ed=N+M+1;
        n=N+M+2;
        memset(num,0,sizeof(num));
        for(int i=1;i<=N;i++){
            int tmp=0;
            for(int j=0;j<M;j++){  //状态压缩
                scanf("%d",&v);
                tmp+=v*bit[j];
            }
            num[tmp]++;
        }
        for(int i=0;i<1024;i++){
            if(num[i]==0) continue;
            addedge(i+1+M,ed,num[i]);
            for(int j=0;j<10;j++)
                if(i&bit[j])
                   addedge(j+1,i+1+M,INF);
        }
        for(int i=1;i<=M;i++){
            scanf("%d",&v);
            addedge(st,i,v);
        }
        int ans=SAP(st,ed);
        if(ans==N) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

 

 
posted @ 2016-06-25 17:40  季末Despair  阅读(136)  评论(0编辑  收藏  举报