zoukankan      html  css  js  c++  java
  • POJ 1149 PIGS(Dinic最大流)

    PIGS
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 20738   Accepted: 9481

    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

    题目链接:POJ 1149

    题意:有M个猪圈,每一个猪圈有初始数量的猪,所有猪都是一样的,有N个人,每一个人有K把钥匙可以打开K个猪圈,对与被打开的猪圈可以进行重新分配猪的数量,每个人又有要买的猪的数量,每一个人按照输入的顺序进来购买,求最后所有人能买到的猪的最大个数。

    解题思路:首先肯定是在源点连到每一个猪圈,容量为该猪圈的初始数量;然后把人连到汇点,容量为人要购买的头数,由于当前买的时候可能对应猪圈已经被重新分配过,因此不是从源点连过来,而是从上一个拥有这个猪圈的钥匙的人连过来一条容量为无穷大的边;若你是第一个开猪圈的人则要从猪圈连过来一条容量为无穷大的边。然后求源点到汇点的最大流即可。

    代码:

    #include <stdio.h>
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <sstream>
    #include <numeric>
    #include <cstring>
    #include <bitset>
    #include <string>
    #include <deque>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LC(x) (x<<1)
    #define RC(x) ((x<<1)+1)
    #define MID(x,y) ((x+y)>>1)
    #define CLR(arr,val) memset(arr,val,sizeof(arr))
    #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
    typedef pair<int, int> pii;
    typedef long long LL;
    const double PI = acos(-1.0);
    const int N = 1110;
    const int M = 110 + N + 110 * N + N;
    struct edge
    {
        int to, nxt, cap;
        edge(int To = 0, int Nxt = 0, int Cap = 0): to(To), nxt(Nxt), cap(Cap) {}
    };
    edge E[M << 1];
    int head[N], d[N], tot;
    int opened[N];
    
    void init()
    {
        CLR(head, -1);
        tot = 0;
        CLR(opened, 0);
    }
    inline void add(int s, int t, int cap)
    {
        E[tot] = edge(t, head[s], cap);
        head[s] = tot++;
        E[tot] = edge(s, head[t], 0);
        head[t] = tot++;
    }
    int bfs(int s, int t)
    {
        CLR(d, -1);
        d[s] = 0;
        queue<int>q;
        q.push(s);
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            for (int i = head[u]; ~i; i = E[i].nxt)
            {
                int v = E[i].to;
                if (d[v] == -1 && E[i].cap > 0)
                {
                    d[v] = d[u] + 1;
                    if (v == t)
                        return 1;
                    q.push(v);
                }
            }
        }
        return ~d[t];
    }
    int dfs(int s, int t, int f)
    {
        if (s == t || !f)
            return f;
        int ret = 0;
        for (int i = head[s]; ~i; i = E[i].nxt)
        {
            int v = E[i].to;
            if (d[v] == d[s] + 1 && E[i].cap > 0)
            {
                int df = dfs(v, t, min(f, E[i].cap));
                if (df > 0)
                {
                    E[i].cap -= df;
                    E[i ^ 1].cap += df;
                    ret += df;
                    f -= df;
                    if (!f)
                        break;
                }
            }
        }
        if (!ret)
            d[s] = -1;
        return ret;
    }
    int Dinic(int s, int t)
    {
        int ret = 0;
        while (bfs(s, t))
            ret += dfs(s, t, INF);
        return ret;
    }
    int main(void)
    {
        int m, n, b, c, i, j, k, id;
        while (~scanf("%d%d", &m, &n))
        {
            init();
            int S = 0, T = n + m + 1;
            for (i = 1; i <= m; ++i)
            {
                scanf("%d", &c);
                add(S, i, c);
            }
            for (i = 1; i <= n; ++i)
            {
                scanf("%d", &k);
                for (j = 0; j < k; ++j)
                {
                    scanf("%d", &id);
                    if (!opened[id])
                        add(id, m + i, INF);
                    else
                        add(opened[id], m + i, INF);
                    opened[id] = m + i;
                }
                scanf("%d", &b);
                add(m + i, T, b);
            }
            printf("%d
    ", Dinic(S, T));
        }
        return 0;
    }
  • 相关阅读:
    关于python的装饰器(初解)
    关于python的创立模块和导入
    2019年春季学期第五周作业
    2019年春季学期第四周作业
    2019年春季学期第三周作业
    pytest
    Python中if __name__ == '__main__':的作用和原理
    oracle中的游标
    oracle中的一些小知识点
    python中str()与repr()函数的区别
  • 原文地址:https://www.cnblogs.com/Blackops/p/6351677.html
Copyright © 2011-2022 走看看