题目链接: Subway Lines Gym - 101908L
给你R个炼油厂,P个加油站,现在,每个炼油厂有着各自的储油量,每个加油站都有着需要的油量。现在给出一些匹配方路线,每条路线无油量运输限制,但跑一边路程会需要花费一定量的时间,问能否满足所有的加油站油量需要,如果可以满足,最少用多少时间?
数据范围: R , P < 1 0 3 R,P<10^3 R,P<103
这题一看,如此分配问题,必定是用网络流没跑了,
但怎么建边呢,原先我想到是跑最小费用最大流,费用优先,但是细想一下,这个原理不同,最小费用最大流需要的是单位流量费用,而这里忽略了单位流量。
于是,我就在费用流的路上渐行渐远了。。。。。
其实,应该用普通的最大流,每次二分建边即可。
#include
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)<
#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");
}