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

【Luogu】P1402 酒店之王 题解

时间:2020-01-30 09:37:44      阅读:68      评论:0      收藏:0      [点我收藏+]

标签:std   之间   根据   space   mes   size   自己   code   一个   

原题链接

这道题,很明显是个配对问题。于是,我们可以想到用网络最大流来做。

先整理一下题目条件。

  1. 很明显,根据贪心思想,要使最多人满意,每个人应该最多睡一个房间(似乎也没有人能睡两个房间),吃一道菜。这就要求一个人最多与一个房间、一道菜配对。
  2. 每个人必须住进喜欢的房间吃到喜欢的菜才算满意。
  3. 每道菜至多让1个人吃,每个房间至多让1个人睡。

于是,我们得出了建图的几大原则:

  1. 菜与房间分别作为一个点。
  2. 为了保证条件1,每个人应该拆成2个点,并在这两个点之间连一条容量为1的边。
  3. 为了保证条件2,应该让每一个人拆成的第一个点与所有自己喜欢的房间对应的点连一条容量为1的边,让每一个人拆成的第二个点与所有自己喜欢的菜对应的点连一条容量为1的边。
  4. 为了保证条件3,应该让源点\(s\)向所有的房间连一条容量为1的边,所有的菜向汇点\(t\)连一条容量为1的边。

放一张对应的图(样例):

技术图片

最后EK跑最大流即可。

Code(超级精简,不到60行):

#include <bits/stdc++.h>
using namespace std;
int n,p,q,head[10005],tot=-1,st,ed,flow[10005],pre[10005],maxflow,vis[10005];
const int INF=0x3f3f3f3f;queue<int> qq;
struct Edge{int to,nxt,flow;}e[200005];
void addedge(int x,int y,int f){
    e[++tot].to=y;e[tot].nxt=head[x];e[tot].flow=f;head[x]=tot; 
    e[++tot].to=x;e[tot].nxt=head[y];e[tot].flow=0;head[y]=tot; 
}
bool bfs(){
    memset(vis,0,sizeof(vis));memset(flow,0,sizeof(flow));flow[st]=INF;
    while(!qq.empty()) qq.pop();
    qq.push(st);vis[st]=1;
    while(!qq.empty()){
        int x=qq.front();qq.pop();
        for(int i=head[x],y;i!=-1;i=e[i].nxt){
            if(e[i].flow>0){
                y=e[i].to;
                if(vis[y]) continue;
                flow[y]=min(flow[x],e[i].flow);pre[y]=i;
                vis[y]=1;qq.push(y);
                if(y==ed) return 1;
            }
        }
    }
    return 0;
}
void doit(){
    while(bfs()){
        int tmp=ed;maxflow+=flow[ed];
        while(tmp!=st){
            e[pre[tmp]].flow-=flow[ed],e[pre[tmp]^1].flow+=flow[ed];
            tmp=e[pre[tmp]^1].to;
        }
    }
}
int main(){
    memset(head,-1,sizeof(head)); 
    scanf("%d%d%d",&n,&p,&q);
    st=0,ed=2*n+p+q+1;
    for(int i=1;i<=n;i++){
        addedge(i+p,i+n+p,1);
        for(int j=1;j<=p;j++){
            int x;scanf("%d",&x);
            if(x) addedge(j,i+p,1);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=q;j++){
            int x;scanf("%d",&x);
            if(x) addedge(i+p+n,n*2+p+j,1);
        }
    }
    for(int i=1;i<=p;i++) addedge(st,i,1);
    for(int i=1;i<=q;i++) addedge(i+n*2+p,ed,1);
    doit();printf("%d\n",maxflow);
    return 0;
}

【Luogu】P1402 酒店之王 题解

标签:std   之间   根据   space   mes   size   自己   code   一个   

原文地址:https://www.cnblogs.com/acceptedzhs/p/12241915.html

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