G - Gasoline Gym - 101908G[二分最大流]
阿新 • • 發佈:2018-11-07
題意:給出R個提供點,P個接收點,每個接收點都要接收滿,還有一個運輸的時間,問最小時間能夠完成所有的運輸。
題解:首先很容易想到費用流,當然T了 ,比賽結束後聽說是二分+最大流,一下就名白了,首先每次都必須要滿流,所以我們只要限制時間即可,限制時間加邊,跑最大流,如果最大流不是滿流,那麼就不滿足,否則滿足條件二分即可。
#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;
}