• POJ1149 PIGS 【最大流量】


    PIGS
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 16555   Accepted: 7416

    Description

    Mirko works on a pig farm that consists of M locked pig-houses and Mirko can't unlock any pighouse because he doesn't have the keys. Customers come to the farm one after another. Each of them has keys to some pig-houses and wants to buy a certain number of pigs. 
    All data concerning customers planning to visit the farm on that particular day are available to Mirko early in the morning so that he can make a sales-plan in order to maximize the number of pigs sold. 
    More precisely, the procedure is as following: the customer arrives, opens all pig-houses to which he has the key, Mirko sells a certain number of pigs from all the unlocked pig-houses to him, and, if Mirko wants, he can redistribute the remaining pigs across the unlocked pig-houses. 
    An unlimited number of pigs can be placed in every pig-house. 
    Write a program that will find the maximum number of pigs that he can sell on that day.

    Input

    The first line of input contains two integers M and N, 1 <= M <= 1000, 1 <= N <= 100, number of pighouses and number of customers. Pig houses are numbered from 1 to M and customers are numbered from 1 to N. 
    The next line contains M integeres, for each pig-house initial number of pigs. The number of pigs in each pig-house is greater or equal to 0 and less or equal to 1000. 
    The next N lines contains records about the customers in the following form ( record about the i-th customer is written in the (i+2)-th line): 
    A K1 K2 ... KA B It means that this customer has key to the pig-houses marked with the numbers K1, K2, ..., KA (sorted nondecreasingly ) and that he wants to buy B pigs. Numbers A and B can be equal to 0.

    Output

    The first and only line of the output should contain the number of sold pigs.

    Sample Input

    3 3
    3 1 10
    2 1 2 2
    2 1 3 3
    1 2 6

    Sample Output

    7

    Source

    题目大意
     Mirko养着一些猪 猪关在一些猪圈里面 猪圈是锁着的
    他自己没有钥匙(汗)
     仅仅有要来买猪的顾客才有钥匙
     顾客依次来 每一个顾客会用他的钥匙打开一些猪圈 买
    走一些猪 然后锁上
     在锁上之前 Mirko有机会又一次分配这几个已打开猪圈
    的猪
     如今给出一開始每一个猪圈的猪数 每一个顾客全部的钥匙
    和要买走的猪数 问Mirko最多能卖掉几头猪

    题解:对于每一个猪圈的第一个购买的人,加入一条源点到这个人的边,权为这个猪圈的猪数,对于后来的且想要购买该猪圈的人。加入一条第一个购买该猪圈的人到该人的边。权为inf,然后加入每一个人到汇点一条边,权值为该人想要购买的猪的头数。至此,构图完毕。


    #include <stdio.h>
    #include <string.h>
    #define inf 0x3fffffff
    #define maxn 110
    #define maxm 1002
    
    int pig[maxm], m, n, sink;
    int G[maxn][maxn], queue[maxn];
    bool vis[maxn]; int Layer[maxn];
    
    bool countLayer() {
        memset(Layer, 0, sizeof(Layer));
        int id = 0, front = 0, now, i; 
        Layer[0] = 1; queue[id++] = 0;
        while(front < id) {
            now = queue[front++];
            for(i = 0; i <= sink; ++i)
                if(G[now][i] && !Layer[i]) {
                    Layer[i] = Layer[now] + 1;
                    if(i == sink) return true;
                    else queue[id++] = i;
                }
        }
        return false;
    }
    
    int Dinic() {
        int minCut, pos, maxFlow = 0;
        int i, id = 0, u, v, now;
        while(countLayer()) {
            memset(vis, 0, sizeof(vis));
            vis[0] = 1; queue[id++] = 0;
            while(id) {
                now = queue[id - 1];
                if(now == sink) {
                    minCut = inf;
                    for(i = 1; i < id; ++i) {
                        u = queue[i - 1];
                        v = queue[i];
                        if(G[u][v] < minCut) {
                            minCut = G[u][v];
                            pos = u;
                        }
                    }
                    maxFlow += minCut;
                    for(i = 1; i < id; ++i) {
                        u = queue[i - 1];
                        v = queue[i];
                        G[u][v] -= minCut;
                        G[v][u] += minCut;
                    }
                    while(queue[id - 1] != pos)
                        vis[queue[--id]] = 0;
                } else {
                    for(i = 0; i <= sink; ++i) {
                        if(G[now][i] && Layer[now] + 1 == Layer[i] && !vis[i]) {
                            vis[i] = 1; queue[id++] = i; break;
                        }
                    }
                    if(i > sink) --id;
                }
            }
        }
        return maxFlow;
    }
    
    int main() {
        //freopen("stdin.txt", "r", stdin);
        int i, keys, num;
        while(scanf("%d%d", &m, &n) == 2) {
            sink = n + 1;
            for(i = 1; i <= m; ++i)
                scanf("%d", &pig[i]);
            memset(G, 0, sizeof(G));
            for(i = 1; i <= n; ++i) {
                scanf("%d", &keys);
                while(keys--) {
                    scanf("%d", &num);
                    if(pig[num] >= 0) {
                        G[0][i] += pig[num]; // 0 is source
                        pig[num] = -i; // 这里是标记第num个猪圈联通的第一个人
                    } else G[-pig[num]][i] = inf;
                }
                scanf("%d", &G[i][sink]);
            }
            printf("%d
    ", Dinic());
        }
        return 0;
    }

    2015.4.20

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int maxn = 105;
    const int inf = 0x3f3f3f3f;
    int G[maxn][maxn], M, N, S, T;
    int pigHouse[maxn*10];
    
    int Dinic(int s, int t);
    
    void getMap()
    {
        memset(G, 0, sizeof(G));
        S = 0; T = N + 1;
    
        int i, j, K, pos;
        for (i = 1; i <= M; ++i)
            scanf("%d", &pigHouse[i]);
    
        for (i = 1; i <= N; ++i) {
            scanf("%d", &K);
            while (K--) {
                scanf("%d", &pos);
                if (pigHouse[pos] >= 0) {
                    G[S][i] += pigHouse[pos];
                    pigHouse[pos] = -i;
                } else {
                    G[-pigHouse[pos]][i] = inf;
                }
            }
            scanf("%d", &G[i][T]);
        }
    }
    
    void solve()
    {
        cout << Dinic(S, T) << endl;
    }
    
    int main()
    {
        while (cin >> M >> N) {
            getMap();
            solve();
        }
        return 0;
    }
    
    int queue[maxn];
    bool vis[maxn]; int Layer[maxn];
    bool countLayer(int s, int t) {
        memset(Layer, 0, sizeof(Layer));
        int id = 0, front = 0, now, i; 
        Layer[s] = 1; queue[id++] = s;
        while(front < id) {
            now = queue[front++];
            for(i = s; i <= t; ++i)
                if(G[now][i] && !Layer[i]) {
                    Layer[i] = Layer[now] + 1;
                    if(i == t) return true;
                    else queue[id++] = i;
                }
        }
        return false;
    }
    // 源点,汇点,源点编号必须最小,汇点编号必须最大
    int Dinic(int s, int t) {
        int minCut, pos, maxFlow = 0;
        int i, id = 0, u, v, now;
        while(countLayer(s, t)) {
            memset(vis, 0, sizeof(vis));
            vis[s] = true; queue[id++] = s;
            while(id) {
                now = queue[id - 1];
                if(now == t) {
                    minCut = inf;
                    for(i = 1; i < id; ++i) {
                        u = queue[i - 1];
                        v = queue[i];
                        if(G[u][v] < minCut) {
                            minCut = G[u][v];
                            pos = u;
                        }
                    }
                    maxFlow += minCut;
                    for(i = 1; i < id; ++i) {
                        u = queue[i - 1];
                        v = queue[i];
                        G[u][v] -= minCut;
                        G[v][u] += minCut;
                    }
                    while(queue[id - 1] != pos)
                        vis[queue[--id]] = false;
                } else {
                    for(i = s; i <= t; ++i) {
                        if(G[now][i] && Layer[now] + 1 == Layer[i] && !vis[i]) {
                            vis[i] = 1; queue[id++] = i; break;
                        }
                    }
                    if(i > t) --id;
                }
            }
        }
        return maxFlow;
    }



    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    结果填空:青蛙爬井
    天上的星星 (前缀和)
    Poj3253 Fence Repair (优先队列)
    Requests+BeautifulSoup+正则表达式爬取猫眼电影Top100(名称,演员,评分,封面,上映时间,简介)
    数字图像处理之几种滤波器
    CodeForces
    直方图部分
    Codeforces Round #431 (Div. 2)
    2017中国大学生程序设计竞赛
    C++中数字与字符串之间的转换(转载自http://www.cnblogs.com/luxiaoxun/)
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4757180.html
Copyright © 2020-2023  润新知