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;
} 

原文地址:https://www.cnblogs.com/popo-black-cat/p/10293865.html

时间: 2024-11-07 19:33:16

P1402 酒店之王的相关文章

洛谷P1402 酒店之王(二分图)

P1402 酒店之王 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只有固定的q道不同的菜. 有一天来了n个客人,每个客人说出了自己喜欢哪些房间,喜欢哪道菜.但是很不幸,可能做不到让所有顾客满意(满意的条件是住进喜欢的房间,吃到喜欢的菜). 这里要怎么分配,能使最多顾客满意呢? 输入输出格式 输入格式: 第一行给出三个正整数表示n,p,q(<=100). 之后n行,每

[洛谷 P1402] 酒店之王

题目描述 Description XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只有固定的q道不同的菜.有一天来了n个客人,每个客人说出了自己喜欢哪些房间,喜欢哪道菜.但是很不幸,可能做不到让所有顾客满意(满意的条件是住进喜欢的房间,吃到喜欢的菜).这里要怎么分配,能使最多顾客满意呢? 输入输出格式 Input/output 输入格式:第一行给出三个正整数表示n,p,q(<=1

luogu P1402 酒店之王

题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只有固定的q道不同的菜. 有一天来了n个客人,每个客人说出了自己喜欢哪些房间,喜欢哪道菜.但是很不幸,可能做不到让所有顾客满意(满意的条件是住进喜欢的房间,吃到喜欢的菜). 这里要怎么分配,能使最多顾客满意呢? 输入输出格式 输入格式: 第一行给出三个正整数表示n,p,q(<=100). 之后n行,每行p个数包含0或1,第

P1402 酒店之王 最大流

\(\color{#0066ff}{ 题目描述 }\) XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只有固定的q道不同的菜. 有一天来了n个客人,每个客人说出了自己喜欢哪些房间,喜欢哪道菜.但是很不幸,可能做不到让所有顾客满意(满意的条件是住进喜欢的房间,吃到喜欢的菜). 这里要怎么分配,能使最多顾客满意呢? $\color{#0066ff}{ 输入格式 } $ 第一行给出三

LUOGU P1402 酒店之王 (网络流)

解题思路 应该比较显然得能看出这是个网络流,将$S$与房间连边,房间与人连边,人与菜连边,菜与汇点连边,边的流量均为1.但这样是错误的,因为有可能一个人跑过去2的流量,所以要将人拆点限流. #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<queue> using namespace std;

「LuoguP1402」 酒店之王(最大流

题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只有固定的q道不同的菜. 有一天来了n个客人,每个客人说出了自己喜欢哪些房间,喜欢哪道菜.但是很不幸,可能做不到让所有顾客满意(满意的条件是住进喜欢的房间,吃到喜欢的菜). 这里要怎么分配,能使最多顾客满意呢? 输入输出格式 输入格式: 第一行给出三个正整数表示n,p,q(<=100). 之后n行,每行p个数包含0或1,第

酒店之王

酒店之王 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只有固定的q道不同的菜. 有一天来了n个客人,每个客人说出了自己喜欢哪些房间,喜欢哪道菜.但是很不幸,可能做不到让所有顾客满意(满意的条件是住进喜欢的房间,吃到喜欢的菜). 这里要怎么分配,能使最多顾客满意呢? 输入输出格式 输入格式: 第一行给出三个正整数表示n,p,q(<=100). 之后n行,每行p个数包含

luoguP1402 酒店之王

为了练dinic优化,再写一道网络流 原题链接: https://www.luogu.org/problemnew/show/P1402 写了很多非常辣鸡的代码还觉得挺对的我... 题意简述:有n个顾客,m道菜,q个房间,顾客满意的条件是能吃到自己喜欢的菜,住自己满意的房间,求最多能让多少顾客满意. 首先建边,源点连向所有的菜,菜向喜欢这道菜的顾客连一条边,顾客向他喜欢的房间连一条边,跑最大流即可. 然而这是错的. 为什么?假设有这个情况,一位顾客同时喜欢多个房间,但是很显然,他最多只能住一个房

luogu 1402 酒店之王

最大流模版题,注意都是将点转换成边.再跑模版即可. #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<queue> using namespace std; const int maxn=1010,inf=9999999; struct node{ int to,w,rev; }; int iter[maxn],level[maxn