【Poj-3436】ACM Computer Factory 最大流

题目链接

这题在寒假个人赛的时候出现过,当时还不会网络流直接就开始 DFS 。

题意

一台电脑有 p 个零件,现在有个工厂有 m 个工作台。

每个工作台每秒可以加工 a 台电脑,并且对接受到的电脑有要求,要求通过 p 个数字给出:

如果第 i 个数字为 0 ,表示接收到的电脑不能包含第 i 个零件;

如果为 1,表示接收到的电脑必须包含第 i 个零件;

如果为 2,表示这个零件有没有都可以;

处理完后的电脑形态也通过 p 个数字给出:

如果第 i 个数字为 0,表示处理完之后没有零件 i

如果为 1,表示处理完之后有零件 i

现在问这个工厂每秒最多可以加工多少台电脑(即处理完后每个零件都存在),并输出路径。

题解

把每一个工作台拆成两个点:输入端和输出端,这两个点之间连一条边。

两层 for 循环枚举所有的工作台,如果第 i 台工作台处理完的电脑 可以供给给第 j 台电脑,那么第 i 台工作台的输出端,向第 j 台的输入端连一条边。

新建一个源点和汇点,源点向输入端要求为全 0 的连一条边,输出端全为 1 的向汇点连一条边,跑 Dinic 即可。

输出路径:先把所有的边保存一下,然后遍历输出端连向输入端的边,如果容量变小了,那么就输出该差值。

代码

/*
 * @Autor: valk
 * @Date: 2020-08-11 12:38:37
 * @LastEditTime: 2020-09-15 19:15:02
 * @Description: 如果邪恶  是华丽残酷的乐章 它的终场 我会亲手写上 晨曦的光 风干最后一行忧伤 黑色的墨 染上安详
 */
#include <algorithm>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int mod = 1e9 + 7;
const int seed = 12289;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int N = 2e2 + 10;

struct parts {
    int a[11], b[11], flow;
} parts[N];
struct Edge {
    int to, cap, next;
    Edge() {};
    Edge(int _to, int _cap, int _next)
    {
        to = _to, cap = _cap, next = _next;
    }
} edge[N * N], cpy[N * N];
struct out {
    int u, v, cap;
    out() {};
    out(int _u, int _v, int _cap)
    {
        u = _u, v = _v, cap = _cap;
    }
} rel[N * N];
int cnt, head[N];
void add(int u, int v, int cap)
{
    edge[cnt] = Edge(v, cap, head[u]);
    head[u] = cnt++;
}
int s, t, p, n;
int dep[N], cur[N];
int bfs()
{
    memset(dep, -1, sizeof(dep));
    memcpy(cur, head, sizeof(head));
    queue<int> q;
    q.push(s);
    dep[s] = 0;
    while (!q.empty()) {
        int now = q.front();
        q.pop();
        for (int i = head[now]; i != -1; i = edge[i].next) {
            int v = edge[i].to, cap = edge[i].cap;
            if (cap && dep[v] == -1) {
                dep[v] = dep[now] + 1;
                q.push(v);
            }
        }
    }
    return dep[t] != -1;
}
int dfs(int u, int flow)
{
    if (u == t)
        return flow;
    int rel = flow;
    for (int i = head[u]; i != -1; i = edge[i].next) {
        if (!rel)
            break;
        cur[u] = i;
        int v = edge[i].to, cap = edge[i].cap;
        if (dep[v] == dep[u] + 1 && cap) {
            int tmp = dfs(v, min(rel, cap));
            rel -= tmp;
            edge[i].cap -= tmp;
            edge[i ^ 1].cap += tmp;
        }
    }
    return flow - rel;
}
void Dinic()
{
    int ans = 0;
    while (bfs()) {
        ans += dfs(s, inf);
    }
    int num = 0;
    for (int i = 1; i <= 2 * n + 2; i++) {
        for (int j = head[i]; j != -1; j = edge[j].next) {
            int v = edge[j].to, cap = edge[j].cap;
            int _v = cpy[j].to, _cap = cpy[j].cap;
            if (cap < _cap && i > n && i <= 2 * n && v <= n) {
                rel[++num] = out(i - n, v, _cap - cap);
                // printf("%d %d %d
", i - n, v, _cap - cap);
                // printf("%d %d %d
", i > n ? i - n : i, v > n ? v - n : v, _cap - cap);
            }
        }
    }
    printf("%d %d
", ans, num);
    for (int i = 1; i <= num; i++) {
        printf("%d %d %d
", rel[i].u, rel[i].v, rel[i].cap);
    }
}
int main()
{
    memset(head, -1, sizeof(head));
    scanf("%d%d", &p, &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &parts[i].flow);
        for (int j = 1; j <= p; j++) {
            scanf("%d", &parts[i].a[j]);
        }
        for (int j = 1; j <= p; j++) {
            scanf("%d", &parts[i].b[j]);
        }
        add(i, n + i, parts[i].flow);
        add(n + i, i, 0);
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (i == j)
                continue;
            int flag = 1;
            for (int k = 1; k <= p; k++) {
                if (parts[j].a[k] == 2)
                    continue;
                if (parts[i].b[k] != parts[j].a[k]) {
                    flag = 0;
                    break;
                }
            }
            if (flag) {
                add(n + i, j, parts[i].flow);
                add(j, n + i, 0);
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        int flag = 1;
        for (int j = 1; j <= p; j++) {
            if (parts[i].a[j] == 2) {
                continue;
            }
            if (parts[i].a[j] != 0)
                flag = 0;
        }
        if (flag) {
            add(2 * n + 1, i, inf);
            add(i, 2 * n + 1, 0);
        }
    }
    for (int i = 1; i <= n; i++) {
        int num = 0;
        for (int k = 1; k <= p; k++) {
            num += parts[i].b[k];
        }
        if (num == p) {
            add(n + i, 2 * n + 2, parts[i].flow);
            add(2 * n + 2, n + i, 0);
        }
    }
    memcpy(cpy, edge, sizeof(edge));
    s = 2 * n + 1, t = 2 * n + 2;
    Dinic();
    return 0;
}
原文地址:https://www.cnblogs.com/valk3/p/13685770.html