最大流,反复跑流

题意:

图片说明

分析:

这题我不会,是看人题解后做的。汗

这题有两个收获:
1.网络流建无向图。

void add(int from, int to, int cap) {
    E[cnt].to = to;
    E[cnt].cap = cap;
    E[cnt].rev = cnt + 1;
    E[cnt].next = head[from];
    head[from] = cnt++;
    E[cnt].to = from;
    E[cnt].cap = cap;           //有向图 为 0
    E[cnt].rev = cnt - 1;
    E[cnt].next = head[to];
    head[to] = cnt++;
}

2.反复跑图:
为什么先跑一遍a1,a1 到 b1,b2
然后再交换一下b1,b2就可以了呢?
推荐这篇博客:https://www.cnblogs.com/chenyushuo/p/5139556.html

代码如下,面向结果编程:

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int inf = 2e9;
const int max_n = 55;
const int max_m = max_n * max_n;
int n, m;
char ma[max_n][max_n];

struct edge
{
    int to, cap, rev, next;
}E[max_m * 2];
int head[max_n * 2];
int cnt = 1;
void add(int from, int to, int cap) {
    E[cnt].to = to;
    E[cnt].cap = cap;
    E[cnt].rev = cnt + 1;
    E[cnt].next = head[from];
    head[from] = cnt++;
    E[cnt].to = from;
    E[cnt].cap = cap;           //有向图 为 0
    E[cnt].rev = cnt - 1;
    E[cnt].next = head[to];
    head[to] = cnt++;
}
void init() {
    fill(head, head + n + 10, false);
    cnt = 1;
    for (int i = 1;i <= n;i++)
        for (int j = 1;j < i;j++)
            if (ma[i][j] == 'O')add(i, j, 2);
            else if (ma[i][j] == 'N') add(i, j, inf);
}

int iter[max_n * 2];
int dist[max_n * 2];
bool searchpath(int s, int t) {
    fill(dist, dist + max_n * 2, -1);
    queue<int> que;dist[s] = 0;
    que.push(s);
    while (!que.empty()) {
        int u = que.front();que.pop();
        for (int i = head[u];i;i = E[i].next) {
            edge& e = E[i];
            if (dist[e.to] != -1 || e.cap == 0)continue;
            dist[e.to] = dist[u] + 1;
            que.push(e.to);
        }
    }return dist[t] != -1;
}

int matchpath(int u, int t, int f) {
    if (u == t)return f;
    for (int& i = iter[u];i;i = E[i].next) {
        edge& e = E[i];
        if (dist[e.to] <= dist[u] || e.cap <= 0)continue;
        int d = matchpath(e.to, t, min(e.cap, f));
        if (d > 0) {
            e.cap -= d;
            E[e.rev].cap += d;
            return d;
        }
    }return false;
}

int dinic(int s, int t) {
    int flow = 0;int f;
    while (searchpath(s, t)) {
        for (int i = 1;i < max_n * 2;i++)iter[i] = head[i];
        while (f = matchpath(s, t, inf))
            flow += f;
    }return flow;
}

int main() {
    ios::sync_with_stdio(0);
    int a1, a2, b1, b2, an, bn;
    while (cin >> n >> a1 >> a2 >> an >> b1 >> b2 >> bn) {
        a1++;a2++;b1++;b2++;an <<= 1;bn <<= 1;
        int start = n + 1;int ed = start + 1;
        for (int i = 1;i <= n;i++)
            for (int j = 1;j <= n;j++)
                cin >> ma[i][j];
        init();
        add(start, a1, an);add(start, b1, bn); 
        add(a2, ed, an);add(b2, ed, bn);
        if (dinic(start, ed) != an + bn)cout << "No\n";
        else {
            init();
            add(start, a1, an);add(a2, ed, an);
            add(start, b2, bn);add(b1, ed, bn);
            if (dinic(start, ed) == an + bn)cout << "Yes\n";
            else cout << "No\n";
        }
    }
}