Gym - 101908G Gasoline 二分+最大流
G - Gasoline Gym - 101908G
题意:给出R个提供点,P个接收点,每个接收点都要接收满,还有一个运输的时间,问最小时间能够完成所有的运输
题解:首先每次都必须要满流,所以我们只要限制时间即可,限制时间加边,跑最大流,如果最大流不是满流,那么就不满足,否则满足条件二分即可。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<stack> #include<cstdlib> #include <vector> #include<queue> using namespace std; #define ll long long #define llu unsigned long long #define INF 0x3f3f3f3f #define PI acos(-1.0) const int maxn = 1e5+5; const int mod = 1e9+7; int P,R,C; int sum; int p[1005],r[1005]; struct E { int u,v,w; }e[20005]; struct Edge { int to, cap, flow; int next; }edge[4*maxn]; int tol; int head[maxn]; int dep[maxn],pre[maxn],cur[maxn]; int gap[maxn]; void init() { tol = 0; memset(head,-1,sizeof (head)); } void addedge (int u,int v,int w,int rw=0) { edge[tol].to = v; edge[tol].cap = w; edge[tol].next = head[u]; edge[tol].flow = 0; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol]. next = head[v]; edge[tol].flow = 0; head[v]=tol++; } int sap(int start,int end, int N) { memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memcpy(cur,head,sizeof(head)); int u = start; pre[u] = -1; gap[0] = N; int ans = 0; int i; while(dep[start] < N) { if(u == end) { int Min = INF; for( i = pre[u];i != -1; i = pre[edge[i^1]. to]) { if(Min > edge[i].cap - edge[i]. flow) Min = edge[i].cap - edge[i].flow; } for( i = pre[u];i != -1; i = pre[edge[i^1]. to]) { edge[i].flow += Min; edge[i^1].flow -= Min; } u = start; ans += Min; continue; } bool flag = false; int v; for( i = cur[u]; i != -1;i = edge[i].next) { v = edge[i]. to; if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = pre[v] = i; break; } } if(flag) { u = v; continue; } int Min = N; for( i = head[u]; i != -1; i = edge[i]. next) { if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } } gap[dep[u]]--; if(!gap[dep[u]]) return ans; dep[u] = Min+1; gap[dep[u]]++; if(u != start) u = edge[pre[u]^1].to; } return ans; } bool judge(int T) { init(); for (int i = 1; i <= P; ++i) { addedge(2 * i - 1, 2 * i, p[i]); addedge(2 * i, 2 * P + 2 * R + 1, INF); } for (int i = 1; i <= C; ++i) if(e[i].w<=T) addedge(2*P+2*e[i].u,2*e[i].v-1,r[e[i].u]); for(int i=1;i<=R;++i) { addedge(0,2*P+2*i-1,INF); addedge(2*P+2*i-1,2*P+2*i,r[i]); } if(sap(0,2*P+2*R+1,2*P+2*R+2) == sum) return true; else return false; } int main() { sum = 0; scanf("%d%d%d",&P,&R,&C); for(int i=1;i<=P;++i) { scanf("%d",p+i); sum += p[i]; } for(int i=1;i<=R;++i) scanf("%d",r+i); for(int i=1;i<=C;++i) scanf("%d%d%d",&e[i].v,&e[i].u,&e[i].w); int l = 1,r = 1000005; bool flag = false; while(l < r) { int mid = (l+r)/2; if(judge(mid)) { r = mid; flag = true; } else l = mid + 1; } if(flag) printf("%d\n",l); else puts("-1"); }