[题解] PowerOJ 1740 圆桌问题 (最大流)

- 传送门 -

 https://www.oj.swust.edu.cn/problem/show/1740

#  1740: 圆桌问题 SPJ Time Limit: 1000 MS Memory Limit: 65536 KB Total Submit: [423](https://www.oj.swust.edu.cn/status?pid=1740) Accepted: [187](https://www.oj.swust.edu.cn/status?pid=1740&result=0) Page View: 1137

Description

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

Input

由文件input.txt提供输入数据。文件第1行有2 个正整数m和n,m表示单位数,n表 示餐桌数,1<=m<=150, 1<=n<=270。文件第2 行有m个正整数,分别表示每个单位的代表 数。文件第3 行有n个正整数,分别表示每个餐桌的容量。

Output

程序运行结束时,将代表就餐方案输出到文件output.txt 中。如果问题有解,在文件第 1 行输出1,否则输出0。接下来的m行给出每个单位代表的就餐桌号。如果有多个满足要 求的方案,只要输出1 个方案。

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

Source

线性规划与网络流24题

 

- 思路 -

 终于打到容量不为 1 的网络流了!!!
 开始转二分图多重匹配!!!
 和前几题也差不多, 只是起点连向 x 集合(单位)的有向边的容量改为该单位代表数, y 集合(餐桌)连向终点的有向边的容量改为餐桌可容纳代表数, 两集合间的边容量还是都是 1 ,然后求最大流.
 
 细节见代码.
 

- 代码 -

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
 
const int N = 500;
const int M = 1e5 + 5;
const int inf = 0x3f3f3f3f;
 
int R[N], C[N];
int CUR[N];
int TO[M], NXT[M], V[M];
int FRM[M], DIS[M], HD[N];
int tot, n, m, sz, cnt, ss, tt;
queue<int> q;
 
void add(int x, int y, int z) {
    FRM[sz] = x; TO[sz] = y; V[sz] = z;
    NXT[sz] = HD[x]; HD[x] = sz++;
    FRM[sz] = y; TO[sz] = x; V[sz] = 0;
    NXT[sz] = HD[y]; HD[y] = sz++;
}
 
bool bfs() {
    memset(DIS, -1, sizeof (DIS));
    q.push(ss);
    DIS[ss] = 0;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i = HD[u]; i != -1; i = NXT[i]) {
            int v = TO[i];
            if (DIS[v] < 0 && V[i]) {
                DIS[v] = DIS[u] + 1;
                q.push(v);
            }
        }
    }
    return DIS[tt] > 0;
}
 
int dfs(int x, int a) {
    if (x == tt) return a;
    int flow = 0, f;
    for (int& i = CUR[x]; i != -1; i = NXT[i]) {
        if (V[i] && DIS[TO[i]] == DIS[x] + 1)
            if (f = dfs(TO[i], min(a, V[i]))) {
                V[i] -= f;
                V[i^1] += f;
                flow += f;
                a -= f;
                if (a == 0) break;
            }
    }
    return flow;
}
 
int dinic() {
    int flow = 0;
    while (bfs()) {
        memcpy(CUR, HD, sizeof (HD));
        flow += dfs(ss, inf);
    }
    return flow;
}
 
void print() {
    for (int i = 1; i <= n; ++i) {
        for (int j = HD[i]; j != -1; j = NXT[j]) {
            if (!V[j]) printf("%d ", TO[j] - n);
        }
        printf("
");
    }
}
 
int main() {
    memset(HD, -1, sizeof (HD));
    scanf("%d%d", &n, &m);
    ss = 0, tt = n + m + 1;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &C[i]);
        add(ss, i, C[i]);
        tot += C[i];
    }
    for (int i = 1; i <= m; ++i) {
        scanf("%d", &R[i]);
        add(n + i, tt, R[i]);
    }
    cnt = sz;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            add(i, n + j, 1);
    if (dinic() == tot) {
        printf("1
");
        print();
    }
    else printf("0
");
    return 0;
}
原文地址:https://www.cnblogs.com/Anding-16/p/7412452.html