假设有来自m 个不同单位的代表参加一次国际会议。每个单位的代表数分别为ri (i =1,2,……,m)。
会议餐厅共有n 张餐桌,每张餐桌可容纳ci (i =1,2,……,n)个代表就餐。
为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,给出满足要求的代表就餐方案。
对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。
输入输出格式
输入格式:
第1 行有2 个正整数m 和n,m 表示单位数,n 表示餐桌数,1<=m<=150, 1<=n<=270。
第2 行有m 个正整数,分别表示每个单位的代表数。
第3 行有n 个正整数,分别表示每个餐桌的容量。
输出格式:
如果问题有解,第1 行输出1,否则输出0。接下来的m 行给出每个单位代表的就餐桌号。如果有多个满足要求的方案,只要输出1 个方案。
输入输出样例
输入样例#1: 复制
4 5 4 5 3 5 3 5 2 6 4输出样例#1: 复制
1 1 2 4 5 1 2 3 4 5 2 4 5 1 2 3 4 5源点向单位Xi连容量为该单位人数的线,Yi向汇点连餐桌容量的线。
每个Xi向每个Yi连容量为1的线
求最大流,若最大流等于单位人数之和,则有解#pragma GCC optimize(2) #include<stdio.h> #include<algorithm> #include<string.h> #include<queue> using namespace std; const int maxn = 1e5; const int inf = 0x3f3f3f3f; typedef long long ll; int head[maxn], level[maxn], r[maxn], c[maxn]; int n, m, tot; struct node { int v, w, next; }edge[maxn]; void addedge(int u, int v, int w) { edge[tot].v = v; edge[tot].w = w; edge[tot].next = head[u]; head[u] = tot++; edge[tot].v = u; edge[tot].w = 0; edge[tot].next = head[v]; head[v] = tot++; return; } bool bfs(int s, int t) { queue<int>q; memset(level, 0, sizeof(level)); level[s] = 1; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if (level[v] == 0 && edge[i].w) { level[v] = level[u] + 1; q.push(v); } } } return level[t] != 0; } int dfs(int s, int t, int f) { if (s == t) { return f; } int cost = 0; for (int i = head[s]; i != -1; i = edge[i].next) { int v = edge[i].v; int w = edge[i].w; if (level[v] == level[s] + 1 && w) { int d = dfs(v, t, min((f - cost), w)); if (d > 0) { edge[i].w -= d; edge[i^1].w += d; cost += d; if (cost == f) { break; } } else { level[v] = 0; } } } return cost; } int dinic(int s, int t) { int flow = 0; while (bfs(s, t)) { flow += dfs(s, t, inf); } return flow; } int main() { //freopen("C://input.txt", "r", stdin); scanf("%d%d", &m, &n); memset(head, -1, sizeof(head)); int sum = 0; int s = 0, t = m + n + 1; for (int i = 1; i <= m; i++) { scanf("%d", &r[i]); addedge(s, i, r[i]); sum += r[i]; } for (int i = 1; i <= n; i++) { scanf("%d", &c[i]); addedge(i + m, t, c[i]); } for (int i = 1; i <= m; i++) { for (int j = m + 1; j <= n + m; j++) { addedge(i, j, 1); } } if (sum == dinic(s, t)) { printf("1\n"); for (int i = 1; i <= m; i++) { for (int j = head[i]; j != -1; j = edge[j].next) { if (edge[j ^ 1].w) { printf("%d ", edge[j].v - m); } } printf("\n"); } } else { printf("0\n"); } return 0; }
网络流24题 P3254 圆桌问题 (二分图多重匹配转最大流)
猜你喜欢
转载自blog.csdn.net/Evildoer_llc/article/details/82928866
今日推荐
周排行