• POJ-1149 PIGS


    题目大意:

    有M个猪圈,每个猪圈都有把锁,卖猪的本身是没有钥匙的,现在有N个顾客要来买猪,而且第i个顾客有a[i]把锁的钥匙,能打开k1,k2,k3...kai的猪圈,称这个时候,你可以调整k1,k2,k3...kai号猪圈里面猪的个数。现在已知每个客户要买多少猪,有哪些锁。问你一天最多能卖出去多少猪。

    解题思路:

    把顾客当作除了源点和汇点的节点,并且设置一个源点和汇点。

    把第一次访问ai个猪圈的顾客与源点添加一条边,容量为开始时猪圈中猪的数目。把在他之后第二个访问该猪圈的顾客与他再添加一条边,容量为INF。以此类推。

    再把每个顾客与汇点添加一条边容量为要买猪的个数。

    这样构图就完成了。然后直接求网络流即可

    代码:

    #include <queue>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    typedef struct node{
        int v, cap, nxt;
        node(int _v = 0, int _cap = 0, int _nxt = 0): v(_v), cap(_cap), nxt(_nxt){}
    }Edge;
    
    const int maxn = 200;
    const int maxm = 2e4 + 10;
    const int INF = 0x3f3f3f3f;
    
    int tot;
    Edge edge[maxm];
    int dis[maxn];
    int head[maxm], num[1005], vis[maxn];
    
    inline int Min(int a, int b){
        return a < b ? a : b;
    }
    void add(int u, int v, int cap){
        edge[tot] = Edge(v, cap, head[u]);
        head[u] = tot++;
        edge[tot] = Edge(u, 0, head[v]);
        head[v] = tot++;
    }
    int bfs(int s, int t){
        queue<int> q;
        while(!q.empty()) q.pop();
        memset(dis, 0, sizeof(dis));
        q.push(s); dis[s] = 1;
        while(!q.empty()){
            int u = q.front(); q.pop();
            if(u == t) break;
            for(int i = head[u]; ~i; i = edge[i].nxt){
                Edge &e = edge[i];
                if(!dis[e.v] && e.cap){
                    dis[e.v] = dis[u] + 1;
                    q.push(e.v);
                }
            }
        }
        return dis[t];
    }
    int dfs(int u, int v, int f){
        if(u == v) return f;
        int sum = 0;
        for(int i = head[u]; ~i; i = edge[i].nxt){
            Edge &e = edge[i];
            if(e.cap && dis[e.v] == dis[u] + 1){
                int ret = dfs(e.v, v, Min(f, e.cap));
                sum += ret; f -= ret;
                e.cap -= ret; edge[i^1].cap += ret;
            }
        }
        return sum;
    }
    int dinic(int s, int t){
        int ret = 0;
        while(bfs(s, t))
            ret += dfs(s, t, INF);
        return ret;
    }
    int main(){
        int a, k, m, n, sum, val;
        while(~scanf("%d%d", &m, &n)){
            tot = 0;
            memset(vis, 0, sizeof(vis));
            memset(head, -1, sizeof(head));
            for(int i = 1; i <= m; ++i){
                scanf("%d", &num[i]);
            }
            for(int i = 1; i <= n; ++i){
                scanf("%d", &a);
                sum = 0;
                for(int j = 1; j <= a; ++j){
                    scanf("%d", &k);
                    if(!vis[k]){ vis[k] = i; sum += num[k]; }
                    else {
                        if(vis[k] == i) continue;
                        add(vis[k], i, INF);
                        vis[k] = i;
                    }
                }
                scanf("%d", &val);
                if(sum > 0) add(0, i, sum);
                add(i, n + 1, val);
            }
            printf("%d
    ", dinic(0, n + 1));
        }
        return 0;
    }


  • 相关阅读:
    iOS推送通知
    KVO内部实现原理
    沙盒目录结构
    UITableView的常用属性和代理方法
    优秀文章的链接
    c++面试题
    递归练习
    c#连接mysql环境配置
    mysql命令详解
    十进制转二进制
  • 原文地址:https://www.cnblogs.com/wiklvrain/p/8179401.html
Copyright © 2020-2023  润新知