[cogs729]圆桌问题(最大流)

传送门

模型

二分图多重匹配问题,可以用最大流解决。

实现

建立二分图,每个单位为X集合中的顶点,每个餐桌为Y集合中的顶点,增设附加源S和汇T。

1、从S向每个Xi顶点连接一条容量为该单位人数的有向边。

2、从每个Yi顶点向T连接一条容量为该餐桌容量的有向边。

3、X集合中每个顶点向Y集合中每个顶点连接一条容量为1的有向边。

求网络最大流,如果最大流量等于所有单位人数之和,则存在解,否则无解。对于每个单位,从X集合对应点出发的所有满流边指向的Y集合的顶点就是该单位人员的安排情况(一个可行解)。

分析

对于一个二分图,每个顶点可以有多个匹配顶点,称这类问题为二分图多重匹配问题。X,Y集合之间的边容量全部是1,保证两个点只能匹配一次(一个餐桌上只能有一个单位的一个人),源

汇的连边限制了每个点匹配的个数。求出网络最大流,如果流量等于X集合所有点与S边容量之和,那么则说明X集合每个点都有完备的多重匹配。

注意 cogs 需要写文件!

——代码

  1 #include <queue>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #define N 50001
  6 #define M 5000001
  7 #define min(x, y) ((x) < (y) ? (x) : (y))
  8
  9 int n, m, cnt, sum, ans, s, t;
 10 int head[N], to[M], val[M], next[M], dis[N], cur[N];
 11
 12 inline int read()
 13 {
 14     int x = 0, f = 1;
 15     char ch = getchar();
 16     for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = -1;
 17     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - ‘0‘;
 18     return x * f;
 19 }
 20
 21 inline void add(int x, int y, int z)
 22 {
 23     to[cnt] = y;
 24     val[cnt] = z;
 25     next[cnt] = head[x];
 26     head[x] = cnt++;
 27 }
 28
 29 inline bool bfs()
 30 {
 31     int i, u, v;
 32     std::queue <int> q;
 33     memset(dis, -1, sizeof(dis));
 34     q.push(s);
 35     dis[s] = 0;
 36     while(!q.empty())
 37     {
 38         u = q.front(), q.pop();
 39         for(i = head[u]; i ^ -1; i = next[i])
 40         {
 41             v = to[i];
 42             if(val[i] && dis[v] == -1)
 43             {
 44                 dis[v] = dis[u] + 1;
 45                 if(v == t) return 1;
 46                 q.push(v);
 47             }
 48         }
 49     }
 50     return 0;
 51 }
 52
 53 inline int dfs(int u, int maxflow)
 54 {
 55     if(u == t) return maxflow;
 56     int v, d, ret = 0;
 57     for(int &i = cur[u]; i ^ -1; i = next[i])
 58     {
 59         v = to[i];
 60         if(val[i] && dis[v] == dis[u] + 1)
 61         {
 62             d = dfs(v, min(val[i], maxflow - ret));
 63             ret += d;
 64             val[i] -= d;
 65             val[i ^ 1] += d;
 66             if(ret == maxflow) return ret;
 67         }
 68     }
 69     return ret;
 70 }
 71
 72 int main()
 73 {
 74     freopen("roundtable.in","r",stdin);
 75     freopen("roundtable.out","w",stdout);
 76     int i, j, x;
 77     m = read();
 78     n = read();
 79     s = 0, t = n + m + 1;
 80     memset(head, -1, sizeof(head));
 81     for(i = 1; i <= m; i++)
 82     {
 83         sum += x = read();
 84         add(s, i, x), add(i, s, 0);
 85         for(j = 1; j <= n; j++)
 86             add(i, j + m, 1), add(j + m, i, 0);
 87     }
 88     for(i = 1; i <= n; i++)
 89     {
 90         x = read();
 91         add(i + m, t, x), add(t, i + m, 0);
 92     }
 93     while(bfs())
 94     {
 95         for(i = s; i <= t; i++) cur[i] = head[i];
 96         ans += dfs(s, 1e9);
 97     }
 98     if(ans ^ sum)
 99     {
100         puts("0");
101         return 0;
102     }
103     puts("1");
104     for(i = 1; i <= m; puts(""), i++)
105         for(j = head[i]; j ^ -1; j = next[j])
106             if(!val[j])
107                 printf("%d ", to[j] - m);
108     return 0;
109 }

时间: 2024-08-07 08:06:50

[cogs729]圆桌问题(最大流)的相关文章

COGS729 圆桌聚餐

问题描述:假设有来自m 个不同单位的代表参加一次国际会议.每个单位的代表数分别为ri(i=1,2,3...m), .会议餐厅共有n张餐桌,每张餐桌可容纳c i(i=1,2...n) 个代表就餐.为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐.试设计一个算法,给出满足要求的代表就餐方案.«编程任务:对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案.«数据输入:由文件roundtable.in提供输入数据.文件第1行有2 个正整数m和n,m表示单位数,n表示餐桌

LibreOJ 6004 圆桌聚餐 (最大流)

题解:天啊,这道最大流真是水的一批……只需要每张桌子向每个单位建一条容量为1的边,源点向桌子建边,容量为桌子能坐的人数;单位向汇点建边,容量为单位人数即可,然后根据单位与桌子的连边值是否为一来了解每个单位配对的桌子即可 代码如下: #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define inf 0x3f3f3

洛谷.3254.圆桌问题(最大流ISAP)

题目链接 日常水题 还是忍不住吐槽这题奇怪的评价 #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar() //#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) const int N=450,M=5e4+5,INF=0x3f3f3f3f,MAXIN=

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

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

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

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

网络流24题 第五题 - PowerOJ1740 CodeVS1905 圆桌问题 二分图多重匹配 网络最大流

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - PowerOJ1740 - 有SPJ - 推荐 题目传送门 - CodeVS1905 - 无SPJ - 0% 通过率(可以用来看题目) 题意概括 有n支队伍,m个组.第i支队伍有a[i]个人,第i个组最多可以有b[i]个人. 现在要求任何两个同队队员不可位于同一组,求是否有方案满足. 输出第一行,表示是否有,如果有,是1,没有的话,输出0: 如果有,接下来n行,第i行a[i]个数,表示第i支队伍的每个人被安

洛谷 P3254 圆桌问题【最大流】

s向所有单位连流量为人数的边,所有饭桌向t连流量为饭桌容量的边,每个单位向每个饭桌连容量为1的边表示这个饭桌只能坐这个单位的一个人.跑dinic如果小于总人数则无解,否则对于每个单位for与它相连.满流.另一端不是s的点则是最终方案 #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int N=1000005,inf

[网络流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) 个代表就餐. 为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐.试设计一个算法, 给出满足要求的代表就

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

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