Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- #define rep(i, a, b) for(int i = a; i < (b); ++i)
- #define all(x) begin(x), end(x)
- #define sz(x) (int)(x).size()
- typedef long long ll;
- typedef pair<int, int> pii;
- typedef vector<int> vi;
- const ll INF = numeric_limits<ll>::max() / 4;
- struct MCMF {
- struct edge {
- int from, to, rev;
- ll cap, cost, flow;
- };
- int N;
- vector<vector<edge>> ed;
- vector<ll> dist, pi;
- vector<edge*> par;
- MCMF(int N) : N(N), ed(N), dist(N), pi(N), par(N) {}
- void addEdge(int from, int to, ll cap, ll cost) {
- if (from == to) return;
- ed[from].push_back(edge{ from,to,sz(ed[to]),cap,cost,0 });
- ed[to].push_back(edge{ to,from,sz(ed[from])-1,0,-cost,0 });
- }
- void path(int s) {
- fill(all(dist), INF);
- dist[s] = 0;
- priority_queue<pair<ll, int>> q;
- q.push({ 0, s });
- while (!q.empty()) {
- auto [d,u] = q.top(); q.pop();
- if (-d > dist[u]) continue;
- for (edge& e : ed[u]) {
- ll val = pi[u] - d - pi[e.to] + e.cost;
- if (e.cap - e.flow > 0 && val < dist[e.to]) {
- dist[e.to] = val;
- par[e.to] = &e;
- q.push({ -dist[e.to], e.to });
- }
- }
- }
- rep(i,0,N) pi[i] = min(pi[i] + dist[i], INF);
- }
- pair<ll, ll> maxflow(int s, int t) {
- ll totflow = 0, totcost = 0;
- while (path(s), dist[t]!=INF) {
- ll c = 0;
- for (edge* x = par[t]; x; x = par[x->from])
- c += x->cost;
- if (c > 0) break;
- ll fl = INF;
- for (edge* x = par[t]; x; x = par[x->from])
- fl = min(fl, x->cap - x->flow);
- totflow += fl;
- for (edge* x = par[t]; x; x = par[x->from]) {
- x->flow += fl;
- ed[x->to][x->rev].flow -= fl;
- }
- }
- rep(i,0,N) for(edge& e : ed[i]) totcost += e.cost * e.flow;
- return {totflow, totcost/2};
- }
- // If some costs can be negative, call this before maxflow:
- void setpi(int s) { // (otherwise, leave this out)
- fill(all(pi), INF); pi[s] = 0;
- int it = N, ch = 1; ll v;
- while (ch-- && it--)
- rep(i,0,N) if (pi[i] != INF)
- for (edge& e : ed[i]) if (e.cap)
- if ((v = pi[i] + e.cost) < pi[e.to])
- pi[e.to] = v, ch = 1;
- assert(it >= 0); // negative cost cycle
- }
- };
- int main() {
- cin.tie(0)->sync_with_stdio(0);
- const int inf = 1e9;
- int r, c, b, t;
- cin >> c >> r >> b >> t;
- vector<vector<vi>> whomst(r, vector<vi>(c));
- vector<string> grid(r);
- rep(i, 0, r) cin >> grid[i];
- pii goal;
- rep(i, 0, r) rep(j, 0, c) if (grid[i][j] == 'K') goal = pii(i, j);
- vector<pii> targets;
- rep(i, 0, t) {
- int a, b;
- cin >> b >> a;
- a--; b--;
- targets.emplace_back(a, b);
- }
- t++;
- targets.push_back(goal);
- rep(i, 0, t) {
- whomst[targets[i].first][targets[i].second].push_back(i);
- }
- using p3 = tuple<int, int, int>;
- vector<vi> dist(t, vi(t, inf));
- vector<pii> dirs = { {0,1},{0,-1},{1,0},{-1,0} };
- rep(i, 0, t) {
- queue<p3> q;
- q.emplace(0, targets[i].first, targets[i].second);
- vector<vi> vis(r, vi(c));
- while (q.size())
- {
- int d, a, b;
- tie(d, a, b) = q.front();
- q.pop();
- if (vis[a][b]) continue;
- vis[a][b] = 1;
- for (auto w : whomst[a][b]) dist[i][w] = d;
- for (auto dir : dirs) {
- pii np = pii(a + dir.first, b + dir.second);
- if (np.first < 0 || np.second < 0 || np.first >= r || np.second >= c) continue;
- if (grid[np.first][np.second] == '#') continue;
- q.emplace(d + 1, np.first, np.second);
- }
- }
- }
- rep(i, 0, t) {
- if (dist[i][t - 1] == inf) {
- cout << "impossible";
- return 0;
- }
- }
- int nodecnt = (t - 1) * 2 + 3;
- MCMF flow(nodecnt);
- flow.addEdge(nodecnt - 2, nodecnt - 3, b, 0);
- rep(i, 0, t - 1) {
- flow.addEdge(nodecnt - 3, i * 2, inf, dist[t - 1][i]);
- }
- rep(i, 0, t - 1) {
- flow.addEdge(i * 2, i * 2 + 1, 1, -inf);
- }
- rep(i, 0, t - 1) {
- flow.addEdge(i * 2 + 1, nodecnt - 1, inf, dist[i][t - 1]);
- }
- rep(i, 0, t - 1) {
- rep(j, i + 1, t - 1) {
- flow.addEdge(i * 2 + 1, j * 2, inf, dist[i][j]);
- }
- }
- flow.setpi(nodecnt - 2);
- auto [_, cost] = flow.maxflow(nodecnt - 2, nodecnt - 1);
- cout << cost + (ll)(t - 1) * inf;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment