活动 - 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;
}
 
                

















