G - Gasoline Gym - 101908G[二分最大流]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38081836/article/details/82998975

题意:给出R个提供点,P个接收点,每个接收点都要接收满,还有一个运输的时间,问最小时间能够完成所有的运输。


题解:首先很容易想到费用流,当然T了 O ( V E f ) O(V * E * f) ,比赛结束后听说是二分+最大流,一下就名白了,首先每次都必须要满流,所以我们只要限制时间即可,限制时间加边,跑最大流,如果最大流不是满流,那么就不满足,否则满足条件二分即可。


c o d e code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
#define met(a, b) memset(a, b, sizeof(a))
ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);}
const int maxn = 1e6+10;
const int inf = 0x3f3f3f3f;
int Next[maxn], top = 0, first[maxn], u[maxn], v[maxn], w[maxn], S = 0, T, dep[maxn], cur[maxn];
void addEdge(int U, int V, int W) {
    u[top] = U;
    v[top] = V;
    w[top] = W;
    Next[top] = first[U];
    first[U] = top++;

    u[top] = V;
    v[top] = U;
    w[top] = 0;
    Next[top] = first[V];
    first[V] = top++;
}

void init() {
    met(first, -1);
    top = 0;
}

bool BFS() {
    //cout << "BFS" << endl;
    met(dep, 0);
    queue<int> q;
    while(!q.empty()) q.pop();
    q.push(S);
    dep[S] = 1;
    while(!q.empty()) {
        int now = q.front();
        q.pop();
        for(int i = first[now]; i != -1; i = Next[i]) {
            int vv = v[i];
            if(dep[vv] == 0 && w[i] > 0) {
                dep[vv] = dep[now] + 1;
                q.push(vv);
            }
        }
    }
    if(dep[T] == 0) return 0;
    else return 1;
}
int DFS(int u, int flow) {
    if(u == T) return flow;
    for(int &i = cur[u]; i != -1; i = Next[i]) {
        if(dep[v[i]] == dep[u] + 1 && w[i] > 0) {
            //cout << flow << " "<< w[i]  << endl;
            int di = DFS(v[i], min(flow, w[i]));
            if(di > 0) {
                //cout << "DFS" << endl;
                w[i] -= di;
                //cout << w[i] << endl;
                w[i ^ 1] += di;
                return di;
            }

        }
    }
    return 0;
}
int dinic() {
    int ans = 0;
    while(BFS()) {
        for(int i = S; i <= T; i++) {
            cur[i] = first[i];
        }
        while(int d = DFS(S, inf)) {
            ans += d;
        }
        //cout << ans << endl;
    }
    return ans;
}

int u1[maxn], v1[maxn], w1[maxn], d[maxn], r[maxn];
int P, R, C;

int sum1 = 0, sum2 = 0;

bool buildGraph(int time) {
    init();
    S = 0, T = P + R + 1;
    rep(i, 1, R) addEdge(S, i, r[i]);
    rep(i, 1, P) addEdge(R + i, T, d[i]);
    rep(i, 1, C) {
        if(w1[i] <= time) {
            addEdge(u1[i], R + v1[i], d[v1[i]]);
        }
    }
    //cout << dinic() << " PK " << sum1 <<endl;
    if(dinic() == sum1) return true;
    else return false;
}

int main() {
    while(~scanf("%d%d%d", &P, &R, &C)) {
        sum1 = 0, sum2 = 0;
        rep(i, 1, P) scanf("%d", &d[i]), sum1 += d[i];
        rep(i, 1, R) scanf("%d", &r[i]), sum2 += r[i];
        if(sum2 < sum1) {
            puts("-1");
            return 0;
        }
        rep(i, 1, C) scanf("%d%d%d", &v1[i], &u1[i], &w1[i]);
        int l = 0, r = 1000000000;
        int ans = -1;
        while(l <= r) {
            int mid = (l + r) >> 1;
            if(buildGraph(mid)) {
                ans = mid;
                //cout << "ans = " << mid << endl;
                r = mid - 1;
            } else {
                l = mid + 1;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38081836/article/details/82998975