hdu 3605 Escape【网路流+状态压缩】

 

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3605

有n个人要移居m个星球,给出每个合适的星球,每个星球最多能容纳的人数,问是否所有人都可以移居。(1≤N≤105,1≤M≤10)(1≤N≤105,1≤M≤10) 

最多有十个星球,而N很大,所以可能会有很多重复,因为每个人去哪个星球最多有2^10中情况,所以可以压缩点,把情况相同的人放到一块,在进行网路流就行;

这道题中,要建立超级源点 0 和超级汇点 (多少种情况+m+1);

邻接表:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#include
using namespace std;
typedef long long ll;
const int N=1050;

struct node
{
    int u,v,flow,cal;
}q;

vectoredge;//记录边
vectorhead[N];//记录每个边的下标(可自行模拟)
int a[N],pre[N],peo[N];
int n,m;

void init(int mm)
{
    edge.clear();
    for(int i=0;i<=mm;i++)
        head[i].clear();
}

void add(int u,int v,int flow)
{
    edge.push_back(node{u,v,0,flow});
    edge.push_back(node{v,u,0,0});
    int tmp=edge.size();
    head[u].push_back(tmp-2);
    head[v].push_back(tmp-1);
}

int solve(int s,int t)//EK算法
{
    int ans=0;
    queueque;
    while(true)
    {
        que.push(s);
        memset(a,0,sizeof(a));
        a[s]=inf;
        while(!que.empty())
        {
            int u=que.front();
            que.pop();
            for(int k=0;kq.flow)
                {
                    que.push(q.v);
                    pre[q.v]=head[u][k];
                    a[q.v]=min(a[u],q.cal-q.flow);
                }
            }
        }
        if(!a[t]) break;
        for(int v=t;v!=s;v=edge[pre[v]].u)
        {
            edge[pre[v]].flow+=a[t];
            edge[pre[v]^1].flow-=a[t];
        }
        ans+=a[t];
    }
    if(ans==n)
        return true;
    return false;
}

int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        memset(peo,0,sizeof(peo));
        int temp,p,po=0;
        for(int i=0;i>=1;
                }
            }
        }
        if(solve(0,t))
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

 

你可能感兴趣的:(网路流)