G

https://lpc.ucfprogrammingteam.org/localFiles/local2019Problems.pdf(G题)

万物皆可网络流,冲冲冲

#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;
}
View Code
原文地址:https://www.cnblogs.com/cherish-lin/p/12550945.html