P1402 酒店之王

Posted popo-black-cat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1402 酒店之王相关的知识,希望对你有一定的参考价值。

  感觉这就是一道蓝题,并不算紫题,但是这道题的思想很重要。

  记得我做过的第一道网络流,用到的就是这个思想,就是拆点。

  因为我们要防止中间的点被用到多次啊……

  别问我为什么,因为我不会再一次解释那是因为只有边才有容量,点没有容量,一个点只要入流等于出流,无论有多少条边经过它,都是可以的。

  那么我们可以把中间点拆开,再连一条边权为1的边即可。

  注意:每个点的标号特备容易弄混……

  代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define maxn 2000005
const int inf=9999999;
struct node
{
    int nxt=-1,to,w;
} edge[maxn];
int dep[maxn],head[maxn];
int n,m,cnt=-1,s,t,p,q;
void add(int a,int b,int c)
{
    edge[++cnt].to=b;
    edge[cnt].nxt=head[a];
    edge[cnt].w=c;
    head[a]=cnt;
}
int bfs()
{
    memset(dep,0,sizeof(dep));
    queue<int> q;
    q.push(s);
    dep[s]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(!dep[to]&&edge[i].w)
            {
                dep[to]=dep[u]+1;
                q.push(to);
            }
        }
    }
    if(dep[t]) return 1;
    else return 0;
}
int dfs(int u,int dist)
{
    if(u==t) return dist;
    int used=0,d=0;
    for(int i=head[u];i!=-1;i=edge[i].nxt)
    {
        if(used==dist) return dist; 
        int to=edge[i].to;
        if(dep[to]==dep[u]+1&&edge[i].w)
        {
            if(d=dfs(to,min(dist-used,edge[i].w)))
            {
                edge[i].w-=d;
                edge[i^1].w+=d;
                used+=d;
            }
        }
    }
    if(!used) dep[u]=0;
    return used;
}
int dinic()
{
    int ans=0;
    while(bfs())
        while(int d=dfs(s,inf))
            ans+=d;
    return ans;
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d%d",&n,&p,&q);
    s=0,t=p+2*n+q+1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=p;j++)
        {
            int x;
            scanf("%d",&x);
            if(x)
            {
                add(j,i+p,1);
                add(i+p,j,0);
            }
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=q;j++)
        {
            int x;
            scanf("%d",&x);
            if(x)
            {
                add(p+n+i,p+2*n+j,1);
                add(p+2*n+j,p+n+i,0);
            }
        }
    for(int i=1;i<=p;i++)
    {
        add(s,i,1);
        add(i,s,0);
    } 
    for(int i=p+1;i<=p+n;i++)
    {
        add(i,i+n,1);
        add(i+n,i,0); 
    }
    for(int i=p+2*n+1;i<=p+2*n+q;i++)
    {
        add(i,t,1);
        add(t,i,0);
    }
    printf("%d",dinic());
    return 0;
} 

 

以上是关于P1402 酒店之王的主要内容,如果未能解决你的问题,请参考以下文章

P1402 酒店之王 最大流

luogu P1402 酒店之王

P1402 酒店之王(网络流)

洛谷 [P1402] 酒店之王

LUOGU P1402 酒店之王 (网络流)

解题报告 『酒店之王(网络最大流 + 拆点)』