zoukankan      html  css  js  c++  java
  • POJ1149 PIGS 网络流

    题意:一个农夫要把养殖的猪卖出去,现有M个猪圈,农夫自己没有猪圈的钥匙。现有N个客户要来买猪,每个客户手中有Ai把钥匙,分别表示成猪圈的编号,并且每个客户需要买一定的猪。这些客户依次过来(编号从小到大),现在农夫可以选择如何将这些猪卖给每一个客户,只要头数不超过需求即可。农夫在处理好每一笔交易后能够将打开的猪圈门之内的猪任意分配。现在问农夫能够卖出最多的猪的数量。

    解法:通过这一题,发现构边的时候其实是有很多技巧的,这题如果把猪圈放到图中的话那么将成为一道不可做题。原因是时间复杂度和空间复杂度太高了。其实可以画出一个简图,然后再通过合并边和合并点来简化构图。由于农夫能够在打开猪圈后任意分配猪。因此如果第j个客户能够买第i个客户买过的猪圈中的猪,那么就可以视作第j个客户代替i先买。也就是说这里有一个边的合并过程。如果每个人都有这种代理的想法,那么农夫(相当于源点)就只要提供猪给第一个打开某个猪圈的客户。因此最后的构边过程可以描述如下:

    1.第i个客户如果无法找到有代理人的猪圈,那么自己成为当前猪圈的代理人,从源点连一条边到i,容量为猪圈中猪的总数;

    2.如果该号猪圈有代理人,那么这个猪圈的代理人 j(注意并不止一个)连一条边到客户 i,容量无穷大,i 也成为该猪圈的代理人。注意这里有一个优化就是只要从最近的代理人那里连一条边到 i 即可,因为其他代理人的边可以通过最近的代理人传递过来。

    3.每个客户连一条到汇点,容量为买猪的数量。

    代码如下:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    int M, N;
    const int SS = 0, TT = 103;
    const int INF = 0x3f3f3f3f;
    // M个猪圈和N个顾客 
    
    struct Edge {
        int v, c, next;
    }e[20005];
    
    
    int cap[1005], link[1005];
    int idx, head[105];
    int que[105];
    int level[105]; // 对每个顶点分一个层
    int front, tail;
    
    void insert(int a, int b, int c) {
        e[idx].v = b, e[idx].c = c;
        e[idx].next = head[a];
        head[a] = idx++;
    }
    
    bool bfs() {
        front = tail = 0;
        que[tail++] = SS;
        memset(level, 0xff, sizeof (level));
        level[SS] = 0;
        while (front != tail) {
            int u = que[front++];
            for (int i = head[u]; i != -1; i = e[i].next) {
                if (!(~level[e[i].v]) && e[i].c) {
                    level[e[i].v] = level[u] + 1;
                    if (e[i].v == TT) return true;
                    que[tail++] = e[i].v;
                }
            }
        }
        return ~level[TT];
    }
    
    int dfs(int u, int sup) {
        if (u == TT) return sup;
        int tf = 0, f;
        for (int i = head[u]; i != -1; i = e[i].next) {
            if (level[u]+1 == level[e[i].v] && e[i].c && (f = dfs(e[i].v, min(e[i].c, sup-tf)))) {
                tf += f;
                e[i].c -= f, e[i^1].c += f;
                if (tf == sup) return sup;
            }
        }
        if (!tf) level[u] = -1;
        return tf;
    }
    
    int dinic() {
        int ret = 0;
        while (bfs()) {
            ret += dfs(SS, INF);
        }
        return ret;
    }
    
    int main() {
        while (scanf("%d %d", &M, &N) != EOF) {
            int x, y, tot;
            idx = 0;
            memset(head, 0xff, sizeof (head));
            for (int i = 1; i <= M; ++i) {
                link[i] = -1;
                scanf("%d", &cap[i]);
            }
            for (int i = 1; i <= N; ++i) {
                tot = 0;
                scanf("%d", &x);
                for (int j = 1; j <= x; ++j) {
                    scanf("%d", &y);
                    if (~link[y]) { // 如果这个节点已经在其他客户出现
                        insert(link[y], i, INF);
                        insert(i, link[y], 0);
                    } else {
                        tot += cap[y];
                    }
                    link[y] = i;
                }
                if (tot) {
                    insert(SS, i, tot);
                    insert(i, SS, 0);
                }
                scanf("%d", &y);
                insert(i, TT, y);
                insert(TT, i, 0);
            }
            printf("%d\n", dinic());
        }
        return 0;
    } 
  • 相关阅读:
    海报
    mailto
    tab+tab
    tab22
    tab
    line-height属性详解
    vertical-align属性详解
    窗口关系及框架、窗口位置、窗口大小、导航和打开窗口
    cursor属性
    深入了解css3新特性
  • 原文地址:https://www.cnblogs.com/Lyush/p/3051898.html
Copyright © 2011-2022 走看看