Escape HDU

来源:互联网 发布:电子日记本软件 编辑:程序博客网 时间:2024/06/06 02:53

点击打开链接

有10^5个人 会超时间 但只有10个星球 可以进行状态压缩(T了两次看了博客才知道..)

假设有5个星球 对于某一个人 他只去 0 和 3 星球 那他的状态就是 1 0 0 1 0 当做二进制压缩后表示就是 2^0+2^3=9

(对于每一个星球 只能选择去或不去 即为1或0 如此这个状态就唯一对应一个二进制数 而这个二进制数与该状态也是唯一对应的)

这样10^5个点就减少为2^10个点 跑模板即可

#include <bits/stdc++.h>using namespace std;#define N 0x3f3f3f3fstruct node{    int v;    int w;    int next;};node edge[50010];int bit[2000],plant[15],first[2000];int dis[2000],gap[2000],cur[2000],pre[2000];int n,m,num,ss,ee,ans;void addedge(int u,int v,int w);void build();void bfs();void isap();int main(){    int i,j,t,sum;    while(scanf("%d%d",&n,&m)!=EOF)    {        memset(bit,0,sizeof(bit));        for(i=1;i<=n;i++)        {            sum=0;            for(j=0;j<m;j++)            {                scanf("%d",&t);                sum+=t*(1<<j);            }            bit[sum]++;        }        for(i=0;i<m;i++)        {            scanf("%d",&plant[i]);        }        build();        isap();        if(ans==n) printf("YES\n");        else printf("NO\n");    }    return 0;}void addedge(int u,int v,int w){    edge[num].v=v;    edge[num].w=w;    edge[num].next=first[u];    first[u]=num++;    return;}void build(){    int pre[15];    int i,j,t,cnt;    memset(first,-1,sizeof(first));    num=0,ss=(1<<m)+m,ee=(1<<m)+m+1;    for(i=1;i<(1<<m);i++)    {        if(bit[i]>0)        {            memset(pre,0,sizeof(pre));            t=i,cnt=0;            while(t>0)            {                pre[cnt++]=t%2;                t/=2;            }            for(j=0;j<m;j++)            {                if(pre[j]==1)                {                    addedge(i,(1<<m)+j,bit[i]);                    addedge((1<<m)+j,i,0);                }            }        }    }    for(i=1;i<(1<<m);i++)    {        addedge(ss,i,bit[i]);        addedge(i,ss,0);    }    for(i=0;i<m;i++)    {        addedge((1<<m)+i,ee,plant[i]);        addedge(ee,(1<<m)+i,0);    }    return;}void bfs(){    queue <int> que;    int i,u,v;    memset(dis,-1,sizeof(dis));    memset(gap,0,sizeof(gap));    que.push(ee);    dis[ee]=0;    while(!que.empty())    {        u=que.front();        que.pop();        gap[dis[u]]++;        for(i=first[u];i!=-1;i=edge[i].next)        {            v=edge[i].v;            if(dis[v]==-1)            {                que.push(v);                dis[v]=dis[u]+1;            }        }    }    return;}void isap(){    int j,u,v,w,flow,minn;    bfs();    memcpy(cur,first,sizeof(first));    memset(pre,-1,sizeof(pre));    ans=0,u=ss,flow=N,num=(1<<m)+m+1;    while(dis[ss]<num)    {        int &i=cur[u];        for(;i!=-1;i=edge[i].next)        {            v=edge[i].v,w=edge[i].w;            if(dis[v]+1==dis[u]&&w>0)            {                pre[v]=i;                u=v,flow=min(flow,w);                if(u==ee)                {                    while(u!=ss)                    {                        edge[pre[u]].w-=flow;                        edge[pre[u]^1].w+=flow;                        u=edge[pre[u]^1].v;                    }                    ans+=flow,flow=N;                }                break;            }        }        if(i==-1)        {            if(--gap[dis[u]]==0) break;            cur[u]=first[u];            minn=num-1;            for(j=first[u];j!=-1;j=edge[j].next)            {                v=edge[j].v,w=edge[j].w;                if(w>0)                {                    minn=min(minn,dis[v]);                }            }            dis[u]=minn+1;            gap[dis[u]]++;            if(u!=ss)            {                u=edge[pre[u]^1].v;            }        }    }    return;}

原创粉丝点击