[BZOJ3504][P3163][CQOI2014]危桥[最大流]

往返一次相当于走两次

危桥流量为2,正常边流量为inf

源点连 \(a_1,a_2\),流量为 \(2 \cdot a_n\)\(b_1,b_2\)连汇点,流量为\(2 \cdot b_n\)

一般想来如果最大流\(\ge \ 2\cdot \left(a_n+b_n\right)\)就输出 Yes

注意到如果\(a\)的流量\(> 2*an\),那么流量可能从\(a_1\)流到\(b_2\),所以交换\(b_1\),\(b_2\)再做一次最大流

#include <bits/stdc++.h>
using namespace std;
 
bool Debug;
 
const int mod = 1e9+7;
const int MAXN = 55, MAXM = 5e5+7, inf = 1e9;
 
struct Edge{
  int v, w, next;
}G[MAXM<<1]; int head[MAXN], n, m, s, t, a0, a1, a2, an, bn, b0, b1, b2, b3, a3, tot = 1, cur[MAXN], dep[MAXN];
char mat[55][53];
inline void add(int u, int v, int w) {
  G[++tot] = (Edge){v, w, head[u]}; head[u] = tot;
  G[++tot] = (Edge){u, 0, head[v]}; head[v] = tot;
}
 
bool bfs(int s, int t) {
    memset(dep, 0x7f, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int>q;
    while(!q.empty()) q.pop();
    dep[s] = 0; q.push(s); 
    while(!q.empty()) {
        int u = q.front(); q.pop();
        for(int i = head[u]; i; i = G[i].next) {
            int v = G[i].v, w = G[i].w;
            if (dep[v] > inf && w) {
                dep[v] = dep[u] + 1;
                if (v == t) return 1;
                q.push(v);
            }
        }
    }
    return dep[t] < inf;
}
 
int dfs(int u, int t, int limit) {
    if (u == t || !limit) return limit;
    int flow = 0, f;
    for(int &i = cur[u]; i; i = G[i].next) {
        int v = G[i].v, w = G[i].w;
        if (dep[v] == dep[u] + 1 && (f = dfs(v, t, min(w, limit)))) {
            flow += f;
            limit -= f;
            G[i].w -= f;
            G[i^1].w += f;
            if (!limit) break;
        }
    }
    return flow;
}
inline int dinic() {
  s = 0, t = n+1; int ret = 0;
  tot = 1, memset(head, 0, sizeof head);
  for(int i = 1; i <= n; ++i) {
    for(int j = 1; j < i; ++j) {
      if (mat[i][j] == 'O') add(i, j, 2), add(j, i, 2);
      else if (mat[i][j] == 'N') add(i, j, inf), add(j, i, inf);
    }
  }
  add(s, a1, 2 * an), add(s, b1, 2 * bn), add(a2, t, 2 * an), add(b2, t, 2 * bn);
  while(bfs(s, t)) ret += dfs(s, t, inf);
  return ret; 
}
int main() {
  #ifdef LOCAL_DEBUG
    Debug = 1;
    // freopen("data.in", "r", stdin);
    // freopen("data.out", "w", stdout);
  #endif
  while(~scanf("%d%d%d%d%d%d%d", &n, &a1, &a2, &an, &b1, &b2, &bn)) {
    ++a1, ++a2, ++b1, ++b2;
    for(int i = 1; i <= n; ++i) scanf("%s", mat[i]+1);
    int ans1 = dinic(); swap(b1, b2); int ans2 = dinic();
    // cout << ans1 << ' ' << ans2 << endl;
    an = (an + bn) * 2;
    puts((ans1>=an && ans2 >= an)?"Yes":"No");
  }
  return 0;
}

posted @ 2018-12-28 16:18  QvvQ  阅读(129)  评论(0编辑  收藏  举报