zoukankan      html  css  js  c++  java
  • luogu P1402 酒店之王 |网络流最大匹配

    题目描述

    XX 酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化。由于很多来住店的旅客有自己喜好的房间色调、阳光等,也有自己所爱的菜,但是该酒店只有 (p) 间房间,一天只有固定的 (q) 道不同的菜,每个房间只能住一位客人,每道菜也只能给一位客人食用。

    有一天来了 (n) 个客人,每个客人说出了自己喜欢哪些房间,喜欢哪道菜。但是很不幸,可能做不到让所有顾客满意(满意的条件是住进喜欢的房间且吃到喜欢的菜)。

    要怎么分配,能使最多顾客满意呢?

    输入格式

    第一行给出三个整数,分别表示表示 (n,p,q)

    之后 (n) 行,每行 (p) 个整数,只可能是 (0)(1),第 (i) 行第 (j) 个数表示第 (i) 个人喜不喜欢第 (j) 个房间((1) 表示喜欢, (0) 表示不喜欢)。

    之后 (n) 行,每行 (q) 个整数,只可能是 (0)(1),第 (i) 行第 (j) 个数表示第 (i) 个人喜不喜欢第 (j) 道菜((1) 表示喜欢, (0) 表示不喜欢)。

    输出格式

    最大的顾客满意数。


    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int N=5e4+5,M=1e6+5,inf=1<<30;
    int nxt[M],head[N],go[M],edge[M],tot=1;
    inline void add(int u,int v,int w){
        nxt[++tot]=head[u],head[u]=tot,go[tot]=v,edge[tot]=w;
        nxt[++tot]=head[v],head[v]=tot,go[tot]=u,edge[tot]=0;
    }
    int n,p,q,now[N];
    int s,t,d[N],maxflow;
    bool bfs(){
        queue<int>q;
        memset(d,0,sizeof(d));
        q.push(s); d[s]=1;
        now[s]=head[s];
        while(q.size()){
            int u=q.front(); q.pop();
            for(int i=head[u];i;i=nxt[i]){
                int v=go[i];
                if(edge[i]&&!d[v]){
                    q.push(v);
                    d[v]=d[u]+1;
                    now[v]=head[v];
                    if(v==t)return 1;
                }
            }
        }
        return 0;
    }
    int dinic(int u,int flow){
        if(u==t)return flow;
        for(int &i=now[u];i;i=nxt[i]){
            int v=go[i];
            if(edge[i]&&d[v]==d[u]+1){
                int k=dinic(v,min(flow,edge[i]));
                if(!k)d[v]=0;
                else{
                    edge[i]-=k;
                    edge[i^1]+=k;
                    return k;
                }
            }
        }
        return 0;
    }
    signed main(){
        cin>>n>>p>>q;
        s=n+n+p+q+2,t=n+n+p+q+1;
        for(int i=1;i<=p;i++)add(s,i,1);
        
        for(int i=1,x;i<=n;i++)
        for(int j=1;j<=p;j++){
            scanf("%d",&x);
            if(x)add(j,i+p,1);
        }
        for(int i=1;i<=n;i++)add(i+p,i+p+n,1);
        for(int i=1,x;i<=n;i++)
        for(int j=1;j<=q;j++){
            scanf("%d",&x);
            if(x)add(i+p+n,i+p+n+n,1);
        }
        for(int j=1;j<=q;j++)add(p+n+n+j,t,1);
        int flow=0;
        while(bfs())
        while(flow=dinic(s,inf))maxflow+=flow;
        cout<<maxflow<<endl;
    }
    
  • 相关阅读:
    c# 使用 Read 读取数据块
    C# TCP/IP通信,Socket通信例子
    c# virtual 关键字 虚方法
    统计图
    oauth2.0 判断接口是否允许跨域
    OI常用模板合集
    CSP2021游记
    8.16 树上问题模拟赛总结
    8.15 图论模拟赛垫底记
    8.14 字符串模拟赛总结
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/12922155.html
Copyright © 2011-2022 走看看