zoukankan      html  css  js  c++  java
  • Luogu P3254 圆桌问题(最大流)

    P3254 圆桌问题

    题面

    题目描述

    假设有来自 (m) 个不同单位的代表参加一次国际会议。每个单位的代表数分别为 (r_i (i =1,2,……,m))

    会议餐厅共有 (n) 张餐桌,每张餐桌可容纳 (c_i (i =1,2,……,n)) 个代表就餐。

    为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,给出满足要求的代表就餐方案。

    对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。

    输入输出格式

    输入格式:

    (1) 行有 (2) 个正整数 (m)(n)(m) 表示单位数, (n) 表示餐桌数, (1 leq m leq 150, 1 leq n leq 270)

    (2) 行有 (m) 个正整数,分别表示每个单位的代表数。

    (3) 行有 (n) 个正整数,分别表示每个餐桌的容量。

    输出格式:

    如果问题有解,第 (1) 行输出 (1) ,否则输出 (0) 。接下来的 (m) 行给出每个单位代表的就餐桌号。如果有多个满足要求的方案,只要输出 (1) 个方案。

    输入输出样例

    输入样例:

    4 5
    4 5 3 5
    3 5 2 6 4
    

    输出样例:

    1
    1 2 4 5
    1 2 3 4 5
    2 4 5
    1 2 3 4 5
    

    思路

    经典的网络流题。设一个 炒鸡 超级源点 (S) 和一个超级汇点 (T) 。对于每一个单位,从源点向单位编号节点连接流量为单位代表数的流;对于每一个餐桌,从餐桌编号节点向汇点连接流量为餐桌容量的流;对于每一组单位和餐桌,连接流量为 (1) 的流。那么若该网络能满流,则可以得出一个可行的方案。统计方案是,只需查询每条边单位和餐桌之间的边是否还有流量即可。

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    int m,n,s,t,sum,ans,dep[455],cur[455];
    int cnt=1,top[455],to[90005],cap[90005],nex[90005];
    inline int read()
    {
        int re=0;
        char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
        return re;
    }
    inline void add_edge(int x,int y,int z)
    {
        to[++cnt]=y,cap[cnt]=z,nex[cnt]=top[x],top[x]=cnt;
        to[++cnt]=x,cap[cnt]=0,nex[cnt]=top[y],top[y]=cnt;
    }
    bool dinic()
    {
        memset(dep,0,sizeof dep);
        memset(cur,0,sizeof cur);
        dep[s]=1,cur[s]=top[s];
        queue<int>Q;
        Q.push(s);
        while(!Q.empty())
        {
            int now=Q.front();Q.pop();
            for(int i=cur[now];i;i=nex[i])
                if(cap[i]&&!dep[to[i]])
                {
                    dep[to[i]]=dep[now]+1,cur[to[i]]=top[to[i]];
                    Q.push(to[i]);
                }
        }
        return dep[t]!=0;
    }
    int dfs(int now,int flow)
    {
        if(now==t) return flow;
        int re=0;
        for(int &i=cur[now];i;i=nex[i])
            if(cap[i]&&dep[to[i]]==dep[now]+1)
            {
                int lzq=dfs(to[i],min(flow,cap[i]));
                if(lzq)
                {
                    re+=lzq,flow-=lzq;
                    cap[i]-=lzq,cap[i^1]+=lzq;
                    if(!flow) break;
                }
            }
        return re;
    }
    int main()
    {
        m=read(),n=read(),s=m+n+1,t=s+1;
        for(int i=1;i<=m;i++)
        {
            int x=read();sum+=x;
            add_edge(s,i,x);
        }
        for(int i=m+1;i<=m+n;i++)
        {
            int x=read();
            add_edge(i,t,x);
        }
        for(int i=1;i<=m;i++)
            for(int j=m+n;j>=m+1;j--)
                add_edge(i,j,1);
        while(dinic()) ans+=dfs(s,INT_MAX);
        if(ans!=sum) printf("0");
        else
        {
            puts("1");
            for(int i=1;i<=m;i++)
            {
                for(int j=top[i];j;j=nex[j])
                {
                    if(j&1) continue;
                    if(!cap[j]) printf("%d ",to[j]-m);
                }
                puts("");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Markdown入门
    HTTP协议 keep-alive连接 与 BS(firefox-thttpd)实验
    emoji探寻之路
    JavaScript实现绑定DOM的定时器插件
    C语言 str2bin 和 bin2str 实现
    LUA OOP 单例模式实现的 一个 方案
    LUA OOP编程实现方法
    以一则LUA实例说明敏捷开发中“分离构造和使用”原则
    HTML 中按钮作为form表单元素提交特性两则 --- 参HTML考标准分析
    分享:一款前端布局工具(alloydesigner)
  • 原文地址:https://www.cnblogs.com/coder-Uranus/p/9736922.html
Copyright © 2011-2022 走看看