• 【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;
    }
    
  • 相关阅读:
    算法总结之 自然数组的排序
    算法总结之 计算数组最小和
    算法总结之 未排序数组中累加和小于或等于给定值的最长子数组长度
    算法总结之 未排序数组中累加和为给定值的最长子数组系列问题
    wget镜像网站并且下载到指定目录 2012-06-20 19:40:56
    用wget做站点镜像
    【亲测好用!】shell批量采集百度下拉框关键词
    网站发的文章有收录 但是没有排名怎么处理
    NGINX + LUA实现复杂的控制
    Linux下php安装Redis扩展
  • 原文地址:https://www.cnblogs.com/valk3/p/13685770.html
Copyright © 2020-2023  润新知