• 【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;
    }
    
    
  • 相关阅读:
    译 PrestaShop开发者指南 第三篇 设置本地安装环境
    译 PrestaShop开发者指南 第二篇 代码规范
    [译]PrestaShop开发者指南 第一篇 基础
    Discuz!X3解读之类引入机制及目录结构
    Discuz的缓存体系
    x3d 规范 在线镜像版
    大容量数据库对表做分割
    链表 队列 堆栈 视频
    How ASP.NET MVC Works?
    SQLServer查看和解决死锁的方法
  • 原文地址:https://www.cnblogs.com/acceptedzhs/p/12241915.html
Copyright © 2020-2023  润新知