zoukankan      html  css  js  c++  java
  • poj 3228 Gold Transportation 二分+网络流

    题目链接

    给出n个城市, 每个城市有一个仓库, 仓库有容量限制, 同时每个城市也有一些货物, 货物必须放到仓库中。 城市之间有路相连, 每条路有长度。 因为有些城市的货物量大于仓库的容量, 所以要运到别的城市,求所有货物都放到仓库中时, 走过的路中, 最长的那条路最短的情况, 输出这条路的长度。

    很容易想到二分, 如果城市之间路的长度小于二分值x, 那么两个城市之间连边, 权值为inf。 源点和所有城市连边, 权值为一开始的货物量, 每个城市和这个城市的仓库连边, 权值inf, 每个仓库和汇点连边, 权值为仓库的容量。 如果最大流的结果不等于一开始所有城市货物量的和, 那么这种情况不满足, 需要加大x, 反之减小x。

    #include <iostream>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <set>
    #include <string>
    #include <queue>
    using namespace std;
    #define pb(x) push_back(x)
    #define ll long long
    #define mk(x, y) make_pair(x, y)
    #define lson l, m, rt<<1
    #define mem(a) memset(a, 0, sizeof(a))
    #define rson m+1, r, rt<<1|1
    #define mem1(a) memset(a, -1, sizeof(a))
    #define mem2(a) memset(a, 0x3f, sizeof(a))
    #define rep(i, a, n) for(int i = a; i<n; i++)
    #define ull unsigned long long
    typedef pair<int, int> pll;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int mod = 1e9+7;
    const int inf = 1061109567;
    const int maxn = 4e5+5;
    int q[maxn*2], head[maxn*2], dis[maxn/10], s, t, num, m, n;
    int a[205], b[205];
    vector <pll> v[201];
    struct node
    {
        int to, nextt, c;
        node(){}
        node(int to, int nextt, int c):to(to), nextt(nextt), c(c){}
    }e[maxn*2];
    void init() {
        num = 0;
        mem1(head);
    }
    void add(int u, int v, int c) {
        e[num] = node(v, head[u], c); head[u] = num++;
        e[num] = node(u, head[v], 0); head[v] = num++;
    }
    int bfs() {
        mem(dis);
        dis[s] = 1;
        int st = 0, ed = 0;
        q[ed++] = s;
        while(st<ed) {
            int u = q[st++];
            for(int i = head[u]; ~i; i = e[i].nextt) {
                int v = e[i].to;
                if(!dis[v]&&e[i].c) {
                    dis[v] = dis[u]+1;
                    if(v == t)
                        return 1;
                    q[ed++] = v;
                }
            }
        }
        return 0;
    }
    int dfs(int u, int limit) {
        if(u == t) {
            return limit;
        }
        int cost = 0;
        for(int i = head[u]; ~i; i = e[i].nextt) {
            int v = e[i].to;
            if(e[i].c&&dis[v] == dis[u]+1) {
                int tmp = dfs(v, min(limit-cost, e[i].c));
                if(tmp>0) {
                    e[i].c -= tmp;
                    e[i^1].c += tmp;
                    cost += tmp;
                    if(cost == limit)
                        break;
                } else {
                    dis[v] = -1;
                }
            }
        }
        return cost;
    }
    
    int dinic() {
        int ans = 0;
        while(bfs()) {
            ans += dfs(s, inf);
        }
        return ans;
    }
    
    int judge(int x, int sum) {
        init();
        for(int i = 1; i<=n; i++) {
            for(int j = 0; j<v[i].size(); j++) {
                if(v[i][j].second<=x) {
                    add(i, v[i][j].first, inf);
                    add(v[i][j].first, i, inf);
                }
            }
            add(s, i, a[i]);
            add(i+n, t, b[i]);
            add(i, i+n, inf);
        }
        if(dinic() == sum)
            return 1;
        return 0;
    }
    
    int main()
    {
        while(cin>>n&&n) {
            int sum = 0;
            for(int i = 1; i<=n; i++) {
                scanf("%d", &a[i]);
                sum += a[i];
            }
            for(int i = 1; i<=n; i++) {
                scanf("%d", &b[i]);
            }
            s = 0, t = 2*n+1;
            cin>>m;
            int x, y, w;
            for(int i = 1; i<=n; i++)
                v[i].clear();
            for(int i = 0; i<m; i++) {
                scanf("%d%d%d", &x, &y, &w);
                v[x].pb(mk(y, w));
            }
            int l = -1, r = 10001;
            while(r-l>1) {
                int m = l+r>>1;
                if(judge(m, sum))
                    r = m;
                else
                    l = m;
            }
            if(l == 10000) {
                puts("No Solution");
                continue;
            }
            cout<<l+1<<endl;
        }
        return 0;
    }
  • 相关阅读:
    SVN服务器搭建(一)
    排序算法二:冒泡排序
    【LeetCode】136. Single Number
    【LeetCode】217. Contains Duplicate
    【LeetCode】189. Rotate Array
    【LeetCode】122. Best Time to Buy and Sell Stock II
    【LeetCode】26. Remove Duplicates from Sorted Array
    【LeetCode】20. Valid Parentheses
    【LeetCode】680. Valid Palindrome II
    【LeetCode】345. Reverse Vowels of a String
  • 原文地址:https://www.cnblogs.com/yohaha/p/5058000.html
Copyright © 2011-2022 走看看