网络流24题之圆桌问题

题目链接:传送门

首先看题,题目要求满足条件的解,首先来考虑是否满足条件,我们不妨假设每个团队到每个桌子的流为1(自己在草稿纸上画一下),在用两个强大的超级点,汇点和源点(这个名词知道吧,不知道可以回去学网络流,这都不知道,做什么这题)将源点和所有的团队相连,流为团队代表数,将桌子和汇点相连,流为桌子的最大上限

那么为什么要这么连呢?因为题目说了每个团队至多一个人在一张餐桌上吃饭,所以设每个团队到每个桌子的流为1,这样保证了每个团队不会有两个或两个以上在同一张桌子吃饭,而因为每个团队的人不是无限的,有一个上限,所以讲他和源点相连,流为团队人数,这样就不会超出范围了,桌子同理

再来看看如何输出方案
其实这很简单
然后枚举每一个团队,如果团队和桌子的边残余容量是0,就证明这里有一个方案

知道了这些以后接下来就是模板题了

#include<bits/stdc++.h>
#define rg register
using namespace std;
typedef long long ll;
inline int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9')  f= (c=='-')?-1:1,c=getchar();
    while(c>='0'&&c<='9')  x=x*10+c-48,c=getchar();
    return f*x;
}
struct node{
    int to,next,v;
}a[100001];
int cnt,head[1000],dep[1001],s=1,t,cur[1001];
void add(int x,int y,int c){
    a[++cnt].to=y;
    a[cnt].next=head[x];
    a[cnt].v=c;
    head[x]=cnt;
}
queue<int> q;
int bfs(){
    memset(dep,0,sizeof(dep));
    q.push(s);
    dep[s]=1;
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(int i=head[now];i;i=a[i].next){
            int v=a[i].to;
            if(a[i].v&&!dep[v])
                dep[v]=dep[now]+1,q.push(v);
        }
    }
    if(!dep[t])
        return 0;
    return 1;
}
int dfs(int k,int list){
    if(k==t)
        return list;
    for(int & i=cur[k];i;i=a[i].next){
        int v=a[i].to;
        if(dep[v]==dep[k]+1&&a[i].v){
            int ans=dfs(v,min(list,a[i].v));
            if(!ans)
                continue;
            a[i].v-=ans;
            if(i%2)
                a[i+1].v+=ans;
            else
                a[i-1].v+=ans;
            return ans;
        }
    }
    return 0;
}
int sum;
int Dinic(){
    int ans=0,k;
    while(bfs()){
        for(int i=1;i<=t;i++)
            cur[i]=head[i];
        while((k=dfs(s,2147483647)))
            ans+=k;
    }
    return ans==sum?1:0;
}
int main(){
    int m=read(),n=read(),x,y;
    t=m+n+2;
    for(int i=1;i<=m;i++)
        x=read(),add(s,i+1,x),add(i+1,s,0),sum+=x;
    for(int i=1;i<=n;i++){
        x=read();
        for(int j=1;j<=m;j++)
            add(j+1,i+m+1,1),add(i+m+1,j+1,0);
        add(i+m+1,t,x),add(t,i+m+1,0);
    }
    int ans=Dinic();
    if(ans==0)
        printf("0"),exit(0);
    printf("1\n");
    for(int i=2;i<=m+1;i++,printf("\n"))
        for(int j=head[i];j;j=a[j].next){
            int v=a[j].to;
             if(!a[j].v&&v!=s)
                printf("%d ",v-m-1);
        }
    return 0;
}

原文地址:https://www.cnblogs.com/hbxblog/p/9708323.html

时间: 2024-10-08 00:25:38

网络流24题之圆桌问题的相关文章

LiberOJ 6004. 「网络流 24 题」圆桌聚餐 网络流版子题

#6004. 「网络流 24 题」圆桌聚餐 内存限制:256 MiB时间限制:5000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 假设有来自 n nn 个不同单位的代表参加一次国际会议.每个单位的代表数分别为 ri r_ir?i??.会议餐厅共有 m mm 张餐桌,每张餐桌可容纳 ci c_ic?i?? 个代表就餐.为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐. 试设计一个算法,给出满足要求的

【网络流24题】圆桌聚餐

LOJ 6004 [网络流24题]圆桌聚餐 题面 假设有来自\(n\)个不同单位的代表参加一次国际会议.每个单位的代表数分别为\(r_i\).会议餐厅共有\(m\)张餐桌,每张餐桌可容纳\(c_i\)个代表就餐. 为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐. 试设计一个算法,给出满足要求的代表就餐方案. 题解 源点向每个单位连一条边,边权是该单位人数: 每个单位向各个餐桌连一条边,边权是1: 每个餐桌向汇点连一条边,边权是餐桌容纳人数. 如果最大流 < 总人数,则无解.若有

【网络流24题】圆桌聚餐(最大流)

[网络流24题]圆桌聚餐(最大流) 题面 Cogs 题解 这道题很简单 首先每个单位的人数限制 直接从源点向单位连边,容量为人数 同样的, 每个桌子向汇点连边,容量为可以坐的人数 因为每个桌子只能够做一个该单位的人 所以,每个单位向桌子连边,容量为1 然后跑一边最大流求方案就行了 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath&

【网络流24题】圆桌问题

题目地址:https://www.luogu.com.cn/problem/P3254 分析&做法 这是一道比较简单的[网络流24题] 很容易想到二分图 左边$M$个点代表$M$个单位,右边$N$个点代表每一个桌子,对于$M$个公司,每一个公司向所有桌子连边,因为一个公司在一个桌子上只能派一个人,所以边权为$1$ 源点$S$连向左边的$M$个点,边权为该单位的人数$ri$,意思是这个公司派出了$ri$个人 右边的$N$个点连向汇点$T$,边权为该桌子的容量$ci$,意思是这个桌子最多坐$ci$个

[cogs729] [网络流24题#5] 圆桌聚餐 [网络流,最大流,多重二分图匹配]

建图:从源点向单位连边,边权为单位人数,从单位向圆桌连边,边权为1,从圆桌向汇点连边,边权为圆桌容量. #include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <queue> #includ

网络流24题之试题库问题

题目链接:传送门 想吐槽一句,这道题和圆桌问题有什么差别吗?貌似并没有什么差别吧,只是在见图的时候改一下而已.详细见网络流24题之圆桌问题 代码 #include<bits/stdc++.h> #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout) #define rg register using namespace std; t

[网络流24题] 圆桌聚餐

729. [网络流24题] 圆桌聚餐 ★★   输入文件:roundtable.in   输出文件:roundtable.out   评测插件 时间限制:1 s   内存限制:128 MB   «问题描述: 假设有来自m 个不同单位的代表参加一次国际会议.每个单位的代表数分别为 ri(i=1,2,3...m), .会议餐厅共有n张餐桌,每张餐桌可容纳c i(i=1,2...n) 个代表就餐. 为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐.试设计一个算法, 给出满足要求的代表就

「网络流24题」 5. 圆桌问题

「网络流24题」 5. 圆桌问题 <题目链接> 二分图多重匹配. 多对多. 匈牙利似乎真的不太好办了. 所以乖乖最大流吧. 套路建模,S->每个单位(边权=单位代表数):每个餐桌->T(边权=餐桌容量):每个单位->每个餐桌(边权=1). 跑最大流. 最大流等于总代表数则有解,否则无解. 每个单位的出边中,每条满流边的终点便是这一单位每个代表的餐桌号. #include <algorithm> #include <climits> #include &

[洛谷P3254] [网络流24题] 圆桌游戏

Description 假设有来自m 个不同单位的代表参加一次国际会议.每个单位的代表数分别为ri (i =1,2,--,m). 会议餐厅共有n 张餐桌,每张餐桌可容纳ci (i =1,2,--,n)个代表就餐. 为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐.试设计一个算法,给出满足要求的代表就餐方案. 对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案. Input 第1 行有2 个正整数m 和n,m 表示单位数,n 表示餐桌数,1<=m<=150, 1