1. 程式人生 > >G - Gasoline Gym - 101908G[二分最大流]

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

題意:給出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; }