[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;
}