Gym - 101908L - Subway Lines (二分+Dinic)

xiaoxiao2025-04-26  11

Subway Lines

题目链接: Subway Lines Gym - 101908L

题意

给你R个炼油厂,P个加油站,现在,每个炼油厂有着各自的储油量,每个加油站都有着需要的油量。现在给出一些匹配方路线,每条路线无油量运输限制,但跑一边路程会需要花费一定量的时间,问能否满足所有的加油站油量需要,如果可以满足,最少用多少时间?

数据范围: R , P &lt; 1 0 3 R,P&lt;10^3 R,P<103


思路

这题一看,如此分配问题,必定是用网络流没跑了,

但怎么建边呢,原先我想到是跑最小费用最大流,费用优先,但是细想一下,这个原理不同,最小费用最大流需要的是单位流量费用,而这里忽略了单位流量。

于是,我就在费用流的路上渐行渐远了。。。。。

其实,应该用普通的最大流,每次二分建边即可。


代码

#include <bits/stdc++.h> using namespace std; #define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++) #define per(i,j,k) for(int i = (int)j;i >= (int)k;i --) #define debug(x) cerr<<#x<<" = "<<(x)<<endl #define mmm(a,b) memset(a,b,sizeof(a)) #define pb push_back typedef double db; typedef long long ll; const int MAXN = (int)2e4+2007; const int INF = (int)0x3f3f3f3f; // 用于表示表示边的结构体(终点、容量、反向边) struct edge{ int to,cap,rev; edge(int to = 0,int cap = 0,int rev = 0):to(to),cap(cap),rev(rev){} }; int SumOut; int N,M; vector<edge> G[MAXN]; int level[MAXN]; //顶点到源点的距离标号 int iter[MAXN]; //当前弧,在其之前的边已经没有用了 //向图中增加一条从s到t容量为cap的边 void add_edge(int from,int to,int cap) { G[from].pb(edge(to,cap,G[to].size())); G[to ].pb(edge(from,0,G[from].size()-1)); } //通过BFS计算从源点出发的距离标号 void bfs(int s){ mmm(level,-1); queue<int> qu; level[s] = 0; qu.push(s); while (!qu.empty()) { int v = qu.front(); qu.pop(); rep(i,0,G[v].size()-1) { edge &e = G[v][i]; if (e.cap > 0 && level[e.to] < 0) { level[e.to] = level[v] + 1; qu.push(e.to); } } } } //通过DFS寻找增广路 int dfs(int v,int t,int f) { if (v == t) return f; for (int &i = iter[v];i < G[v].size();i ++) { edge &e = G[v][i]; if (e.cap > 0 && level[v] < level[e.to]) { int d = dfs(e.to,t,min(f,e.cap)); if (d > 0) { e.cap -= d; G[e.to][e.rev].cap += d; return d; } } } return 0; } //求解从s到t的最大流 int max_flow(int s,int t){ int flow = 0; for (;;) { bfs(s); if (level[t] < 0) return flow; mmm(iter,0); int f; while ((f = dfs(s,t,INF)) > 0) flow += f; } } void init(){ rep(i,1,N) G[i].clear(); } int P,R; int in[MAXN]; int out[MAXN]; struct Node{ int u,v,cost; Node(int u = 0,int v = 0,int cost = 0):u(u),v(v),cost(cost){} }; Node tmp[MAXN]; int s,t; bool OK(int m) { init(); rep(i,1,M) { if (tmp[i].cost <= m) add_edge(tmp[i].u,tmp[i].v,INF); } rep(i,M+1,R+P+M) { add_edge(tmp[i].u,tmp[i].v,tmp[i].cost); } int res = max_flow(s,t); return res == SumOut; } int main() { scanf("%d %d %d",&P,&R,&M); rep(i,1,P) { scanf("%d",&out[i]); SumOut += out[i]; } rep(i,1,R) scanf("%d",&in[i]); N = P+R; s = ++N; t = ++N; rep(i,1,M) { int x,y,w; scanf("%d %d %d",&x,&y,&w); tmp[i] = Node(y,x+R,w); } rep(i,1,R) { tmp[i+M] = Node(s,i,in[i]); } rep(i,1,P) { tmp[i+M+R] = Node(i+R,t,out[i]); } int l = 0,r = INF; while (l <= r) { int m = l+r>>1; if (OK(m)) r = m-1; else l = m+1; } if (l != INF+1) printf("%d\n",l); else printf("-1\n"); }
转载请注明原文地址: https://www.6miu.com/read-5029163.html

最新回复(0)