G - Cooperative Escape Gym - 102343G (费用流)
https://lpc.ucfprogrammingteam.org/localFiles/local2019Problems.pdf(G题)
万物皆可网络流,冲冲冲
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<map> #include<set> #include<cmath> #include<deque> #include<queue> #include<stack> #include<string> #include<bitset> #include<cstdio> #include<vector> #include<iomanip> #include<cstring> #include<sstream> #include<iostream> #include<algorithm> //#include<bits/stdc++.h> #define fi first #define se second #define eps 1e-2 #define ll long long #define pb push_back #define maxn 210050 #define inf 0x3f3f3f3f #define INF 0x3f3f3f3f3f3f3f3f #define P pair<ll, ll> #define pi acos(-1) #define lson l,mid,rt*2 #define rson mid+1,r,rt*2+1 #define lowbit(x) (x&(-x)) #define SZ(x) ((int)(x).size()) #define met(a,x) memset(a,x,sizeof(a)) #define openin(x) freopen(x, "r", stdin) #define openout(x) freopen(x, "w",stdout) #define rep(i,a,b) for(ll i = a;i <= b;i++) #define bep(i,a,b) for(ll i = a;i >= b;i--) #define ios() ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); using namespace std; const ll mod = 1000000007; inline int read() { int x = 0; char ch = getchar(); for (; !isdigit(ch); ch = getchar()); for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0'; return x; } int cnt, head[maxn], vis[maxn], pre[maxn], last[maxn], flow[maxn]; int n, m, s, t; ll dis[maxn], h[maxn]; struct node { ll v, w, c, net; }e[maxn]; void add(int u, int v, int w, int c) { e[cnt] = node { v, w, c, head[u] }; head[u] = cnt++; } void add_Edge(int u, int v, int w, int c) { add(u, v, w, c); add(v, u, 0, -c); } bool spfa(int s, int t) { rep(i, 0, n*m) { vis[i] = 0; pre[i] = -1; last[i] = -1; flow[i] = inf; dis[i] = inf; } dis[s] = 0; queue<int>que; que.push(s); while (!que.empty()) { int u = que.front(); que.pop(); vis[u] = 0; for (int i = head[u]; i != -1; i = e[i].net) { int v = e[i].v; int w = e[i].w; int c = e[i].c; if (dis[v] > dis[u] + c && w > 0) { dis[v] = dis[u] + c; pre[v] = u; last[v] = i; flow[v] = min(flow[u], w); if (!vis[v]) { vis[v] = 1; que.push(v); } } } } return dis[t] != inf; } int Dijkstra(int s, int t) { rep(i, 0, n*m) { vis[i] = 0; pre[i] = -1; last[i] = -1; flow[i] = inf; dis[i] = inf; } dis[s] = 0; priority_queue<P, vector<P>, greater<P> >que; que.push(P(0, s)); while (!que.empty()) { P now = que.top(); que.pop(); int u = now.second; if (vis[u])continue; for (int i = head[u]; i != -1; i = e[i].net) { int v = e[i].v; int w = e[i].w; int c = e[i].c; if (!vis[v] && w > 0 && dis[v] > dis[u] + c + h[u] - h[v]) { dis[v] = dis[u] + c + h[u] - h[v]; pre[v] = u; last[v] = i; flow[v] = min(flow[u], w); que.push(P(dis[v], v)); } } } return dis[t] != inf; } char a[100][100]; int dx[4] = { -1,1,0,0 };//上下左右 int dy[4] = { 0,0,-1,1 }; int main() { cin >> n >> m; rep(i, 0, n*m)head[i] = -1; rep(i, 1, n) { rep(j, 1, m) { cin >> a[i][j]; int v = (i - 1)*m + j; if (a[i][j] == 'B')add_Edge(0, v, 1, 0); else if (a[i][j] == 'C')add_Edge(0, v, 1, 0); else if (a[i][j] == 'F') { t = v; } } } rep(i, 1, n) { rep(j, 1, m) { rep(k, 0, 3) { int tx = i + dx[k]; int ty = j + dy[k]; if (a[i][j] != 'x' && tx >= 1 && tx <= n && ty >= 1 && ty <= m && a[tx][ty] != 'x') { int u = (i - 1)*m + j; int v = (tx - 1)*m + ty; add_Edge(u, v, 1, 1); } } } } ll mx_flow = 0, mi_cost = 0; while (Dijkstra(s, t)) { //起点0,终点t <--> F mx_flow += flow[t]; mi_cost += flow[t] * (dis[t] - h[s] + h[t]); for (int u = t; u != s; u = pre[u]) { ll cur = last[u]; e[cur].w -= flow[t]; e[cur ^ 1].w += flow[t]; } rep(i, 0, n*m)h[i] += dis[i]; } if (mx_flow == 2)cout << mi_cost << endl;//两人都可到达Ford else cout << -1 << endl; getchar(); getchar(); return 0; }