• 【Luogu】P1402 酒店之王 题解


    原题链接

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

    先整理一下题目条件。

    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
    ",maxflow);
        return 0;
    }
    
    
  • 相关阅读:
    Python基础(14)_python模块之configparser模块、suprocess
    Python基础(13)_python模块之re模块(正则表达式)
    Python基础(12)_python模块之sys模块、logging模块、序列化json模块、pickle模块、shelve模块
    Python基础(11)_python模块之time模块、rando模块、hashlib、os模块
    Python基础(10)_内置函数、匿名函数、递归
    python中内建函数isinstance的用法
    Python基础(9)_生成器(yield表达式形式)、面向过程编程
    Python基础(8)_迭代器、生成器、列表解析
    Python基础(7)_闭包函数、装饰器
    Python基础(6)_函数
  • 原文地址:https://www.cnblogs.com/acceptedzhs/p/12241915.html
Copyright © 2020-2023  润新知