2179. 圆桌问题(最大流,二分图多重匹配)

活动 - AcWing

假设有来自 m 个不同单位的代表参加一次国际会议。

每个单位的代表数分别为 ri(i=1,2,…,m)。

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

为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。

试设计一个算法,给出满足要求的代表就餐方案。

输入格式

第 1 行有 2 个正整数 m 和 n,m 表示单位数,n 表示餐桌数。

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

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

输出格式

如果问题有解,在第 1 行输出 1,否则输出 0。

接下来的 m 行给出每个单位代表的就餐桌号。

如果有多个满足要求的方案,只要求输出 1 个方案。

数据范围

1≤m≤150
1≤n≤270
1≤ri,ci≤100

输入样例:
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

解析: 

最大流问题的建图: 

建立一个虚拟源点,从源点向每个公司代表的节点连一条容量为x(该公司的代表人数)的边;建立一个汇点,每个餐桌向连汇点一条容量为y(该餐桌容纳人数)的边。每个公司代表人数的节点向每张餐桌连一条容量为1的边 

检验原问题解的集合与可行流的集合一一对应: 

角度一:原问题的每一个解对应一个可行流 

角度二:每一个可行流对应原问题的每一个解 

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
#include<sstream>
#include<deque>
#include<unordered_map>
#include<unordered_set>
#include<bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 430 + 5, M = (150 * 270 + N) * 2, INF = 0x3f3f3f3f;
int n, m, S, T;
int h[N], e[M], f[M], ne[M], idx;
int q[N], d[N], cur[N];

void add(int a, int b, int c) {
	e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx++;
	e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx++;
}

bool bfs() {
	int hh = 0, tt = 0;
	memset(d, -1, sizeof d);
	q[0] = S, d[S] = 0, cur[S] = h[S];
	while (hh <= tt) {
		int t = q[hh++];
		for (int i = h[t]; i != -1; i = ne[i]) {
			int j = e[i];
			if (d[j] == -1 && f[i]) {
				d[j] = d[t] + 1;
				cur[j] = h[j];
				if (j == T)return 1;
				q[++tt] = j;
			}
		}
	}
	return 0;
}

int find(int u, int limit) {
	if (u == T)return limit;
	int flow = 0;
	for (int i = cur[u]; i != -1 && flow < limit; i = ne[i]) {
		int j = e[i];
		cur[u] = i;
		if (d[j] == d[u] + 1 && f[i]) {
			int t = find(j, min(f[i], limit - flow));
			if (!t)d[j] = -1;
			f[i] -= t, f[i ^ 1] += t, flow += t;
		}
	}
	return flow;
}

int dinic() {
	int ret = 0, flow;
	while (bfs())while (flow = find(S, INF))ret += flow;
	return ret;
}

int main() {
	int sum = 0;
	cin >> m >> n;
	memset(h, -1, sizeof h);
	S = 0, T = n + m + 1;
	for (int i = 1,a; i <= m; i++) {
		scanf("%d", & a);
		add(S, i, a);
		sum += a;
	}
	for (int i = 1; i <= m; i++) {
		for (int j = m + 1; j <= n + m; j++) {
			add(i, j, 1);
		}
	}
	for (int i = m+1, a; i <= n+m; i++) {
		scanf("%d", &a);
		add(i, T, a);
	}
	if (dinic() != sum)cout << 0 << endl;
	else {
		cout << 1 << endl;
		for (int u = 1; u <= m; u++) {
			for (int i = h[u]; i != -1; i = ne[i]) {
				if (!f[i]) printf("%d ", e[i]-m);
			}
			printf("\n");
		}
	}
	return 0;
}

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-21 02:18:04       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-21 02:18:04       106 阅读
  3. 在Django里面运行非项目文件

    2024-02-21 02:18:04       87 阅读
  4. Python语言-面向对象

    2024-02-21 02:18:04       96 阅读

热门阅读

  1. 用Kali Linux自带的MSF远控windows系统

    2024-02-21 02:18:04       54 阅读
  2. Go 空切片 VS nil切片

    2024-02-21 02:18:04       52 阅读
  3. 51%攻击

    2024-02-21 02:18:04       56 阅读
  4. 分页工具类

    2024-02-21 02:18:04       51 阅读
  5. 1. A. Did We Get Everything Covered?(构造、思维)

    2024-02-21 02:18:04       51 阅读
  6. iocp简单例子

    2024-02-21 02:18:04       53 阅读
  7. Kubernetes 100个常用命令!

    2024-02-21 02:18:04       51 阅读
  8. 数组排序(C语言)

    2024-02-21 02:18:04       53 阅读
  9. 发NLP方向顶会这24个研究方向可以卷

    2024-02-21 02:18:04       45 阅读
  10. neo4j常用代码

    2024-02-21 02:18:04       68 阅读
  11. C# 中的回调函数

    2024-02-21 02:18:04       43 阅读