码迷,mamicode.com
首页 > 其他好文 > 详细

hdu3605(最大流+状态压缩)

时间:2015-02-17 23:36:18      阅读:640      评论:0      收藏:0      [点我收藏+]

标签:

 

传送门:Escape

题意:给出每个人适合住的星球信息和该星球能住多少人 ,第一行给出n m 代表有 n 个人 m 个星球,然后接下来n行每行m个数字 1代表适合第 i 个星球 0 代表不适合第 i 个星球,最后一行m个数表示第 i 个星球最多可以住多少个人,问是不是所有人都可以住到星球上。

分析:很裸的最大流,但刚开始直接去建图,100W级别的边MLE了,就算没MLE也会TLE的,因此需要状态压缩,m<=10,最多1024种状态,边数降成1W级别,最大流妥妥的A了。

技术分享
#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <limits.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-6
#define N 10010
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PII pair<int,int>
using namespace std;
inline int read()
{
    char ch=getchar();int x=0,f=1;
    while(ch>9||ch<0){if(ch==-)f=-1;ch=getchar();}
    while(ch<=9&&ch>=0){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
int n,m,sum,vs,vt,tot,NV;
int pre[N],cur[N],h[N],q[N];
struct edge
{
    int u,v,w,next;
    edge() {}
    edge(int u,int v,int w,int next):u(u),v(v),w(w),next(next) {}
} e[N*20];
void addedge(int u,int v,int w)
{
    e[tot]=edge(u,v,w,pre[u]);
    pre[u]=tot++;
    e[tot]=edge(v,u,0,pre[v]);
    pre[v]=tot++;
}
void init()
{
    memset(pre,-1,sizeof(pre));
    tot=0;
}

/*******************dinic************************/
int bfs()
{
    int head=0,tail=1;
    memset(h,-1,sizeof(h));
    q[0]=vs;h[vs]=0;
    while(head!=tail)
    {
        int u=q[head++];
        for(int i=pre[u];~i;i=e[i].next)
        {
            int v=e[i].v,w=e[i].w;
            if(w&&h[v]==-1)
            {
                h[v]=h[u]+1;
                q[tail++]=v;
            }
        }
    }
    return h[vt]!=-1;
}

int dfs(int u,int flow)
{
    if(u==vt)return flow;
    int used=0;
    for(int i=cur[u];~i;i=e[i].next)
    {
        int v=e[i].v,w=e[i].w;
        if(h[v]==h[u]+1)
        {
            w=dfs(v,min(flow-used,w));
            e[i].w-=w;e[i^1].w+=w;
            if(e[i].w)cur[u]=i;
            used+=w;
            if(used==flow)return flow;
        }
    }
    if(!used)h[u]=-1;
    return used;
}
int dinic()
{
    int res=0;
    while(bfs())
    {
        for(int i=vs;i<=vt;i++)cur[i]=pre[i];
        res+=dfs(vs,inf);
    }
    return res;
}
/********************dinic***********************/
int x,state,a[N];
void build()
{
    vs=0;vt=(1<<m)+m+1;
    memset(a,0,sizeof(a));
    for(int i=1;i<=n;i++)
    {
        state=0;
        for(int j=0;j<m;j++)
        {
            x=read();
            if(x)state|=(1<<j);
        }
        a[state]++;
    }
    for(int i=0;i<(1<<m);i++)
    {
        if(a[i])
        {
            addedge(vs,i+1,a[i]);
            for(int j=0;j<m;j++)
            {
                if(i&(1<<j))
                    addedge(i+1,j+1+(1<<m),a[i]);
            }
        }
    }
    for(int i=0;i<m;i++)
    {
        x=read();
        addedge((1<<m)+i+1,vt,x);
    }
    if(dinic()==n)puts("YES");
    else puts("NO");
}
int main()
{
    while(scanf("%d%d",&n,&m)>0)
    {
        init();
        build();
    }
}
View Code

 

hdu3605(最大流+状态压缩)

标签:

原文地址:http://www.cnblogs.com/lienus/p/4295545.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!