题解 BZOJ#4669. 抢夺
为什么别人一眼二分答案然后就莽过去了,我想半天不知道咋二分。后来发现压根不需要二分。
可以发现的性质是,我们一定优先走最短路,但是容量有限,一些较长路能够分流。但是不管怎样,我们一定走的是最短的若干条路径。
首先建出费用流的图,对于一条长为 \(d\) 的最短路以及流量 \(f\),答案为 \(d+(k-f-1)/f+1\)。
而每新加入一条较劣的长为 \(d'\) 最短路,前 \(d\) 时间所有路径分流,后 \(d'-d\) 的时间会让之前的最短路尽量多通过人数。
不断增广然后取最优答案即可。
#include <bits/stdc++.h>
using i64 = long long;
const i64 Inf = 0x3f3f3f3f3f3f3f3f;
struct Graph {
std::vector<int> head;
struct Edge { int nxt, to; i64 flow, cost; };
std::vector<Edge> e;
Graph(int n) : head(n + 1, -1) {}
void add(int u, int v, i64 f, i64 c) {
e.emplace_back(Edge{head[u], v, f, c});
head[u] = e.size() - 1;
}
void add_flow(int u, int v, i64 f, i64 c) {
add(u, v, f, c);
add(v, u, 0, -c);
}
};
struct Dinic {
Graph &G;
std::vector<i64> dis;
std::vector<int> cur, inq, vis;
Dinic(int n, Graph &G)
: G(G), dis(n + 1), cur(n + 1), inq(n + 1), vis(n + 1) {}
i64 spfa(int S, int T) {
std::fill(dis.begin(), dis.end(), Inf);
std::queue<int> q;
q.push(S);
inq[S] = true;
dis[S] = 0;
while (!q.empty()) {
int u = q.front();
q.pop();
inq[u] = false;
for (int i = G.head[u]; ~i; i = G.e[i].nxt) {
int v = G.e[i].to;
if (G.e[i].flow > 0 && dis[v] > dis[u] + G.e[i].cost) {
dis[v] = dis[u] + G.e[i].cost;
if (!inq[v]) {
q.push(v);
inq[v] = true;
}
}
}
}
return dis[T];
}
i64 dfs(int u, i64 lim, int T) {
if (!lim || u == T)
return lim;
i64 rest = lim;
vis[u] = true;
for (int &i = cur[u]; ~i; i = G.e[i].nxt) {
int v = G.e[i].to;
if (G.e[i].flow > 0 && dis[v] == dis[u] + G.e[i].cost && !vis[v]) {
i64 rlow = dfs(v, std::min(rest, (i64) G.e[i].flow), T);
if (!rlow) dis[v] = Inf;
G.e[i].flow -= rlow;
G.e[i ^ 1].flow += rlow;
rest -= rlow;
if (!rest) break;
}
}
vis[u] = false;
return lim - rest;
}
i64 solve(int S, int T, i64 k) {
i64 lastd = 0;
i64 ans = Inf;
i64 sumf = 0;
while (k > 0) {
i64 maxd = spfa(S, T);
if (maxd == Inf)
break;
i64 flow = 0;
i64 rlow;
std::copy(G.head.begin(), G.head.end(), cur.begin());
while (rlow = dfs(S, Inf, T), rlow > 0)
flow += rlow;
// std::cerr << maxd << ' ' << flow << '\n';
k -= flow + (maxd - lastd) * sumf;
sumf += flow;
ans = std::min(ans, maxd + (k - 1) / sumf + 1);
lastd = maxd;
}
return ans;
}
};
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m, k;
while (std::cin >> n >> m >> k) {
Graph G(n);
for (int i = 0; i < m; ++i) {
int u, v, w;
std::cin >> u >> v >> w;
++u;
++v;
G.add_flow(u, v, w, 1);
}
if (k == 0) {
std::cout << 0 << '\n';
continue;
}
i64 ans = Dinic(n, G).solve(1, n, k);
if (ans == Inf)
std::cout << "No solution" << '\n';
else
std::cout << ans << '\n';
}
return 0;
}

浙公网安备 33010602011771号