一眼看出网络流, 可惜不会写...建模方法当时实在想不出来。
可以考虑设置一个源点流向a1和b1, 再将a2和b2流向设置的另一个汇点, 这样只要确定最大流等于最开始流入的流量就够了。
然后呵呵。 要是从a1出发跑到了b2, Bob只能看着Alice的背影渐行渐远, 消失在桥的那一头, 正要踏步去追寻, 却发现脚下一空, 原来危桥早已塌陷, 而Alice回头时, 才发现那人已经坠下深渊。于是Alice交出闪现...(此处无限脑补)总之, 为了维护世界的和平, 我们不容许这样的网络流存在。
解决方法也很简单, 只要将Alice或者Bob的起点和终点交换一下就行了, 因为如果真的出现了Bob坠下海底的局面, 来世再见会发现两人在同一座桥相遇难道不是吗? 所以说今世无缘的话, 来世也不要再见, 大家各走各的路才是真谛。
接下来就是正常的网络流了, 由于不会邻接矩阵的写法, 这里还是前向星。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 50 + 3
#define M 5000 + 10
#define INF 1000000000
using namespace std;
struct edge
{
int to, cap, flow, next;
}e[M];
char ch[N][N];
int n, a1, a2, an, b1, b2, bn, ans;
int s, t, num, p[N], flag[N], d[N], now[N];
void add(int x, int y, int z)
{
e[++num].to = y;
e[num].cap = z;
e[num].next = p[x];
p[x] = num;
}
void read()
{
for (int i = 1; i <= n; ++i)
{
getchar();
for (int j = 1; j <= n; ++j)
ch[i][j] = getchar();
}
}
void init()
{
memset(e, 0, sizeof e);
memset(p, 0, sizeof p);
num = 1;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
switch(ch[i][j])
{
case 'X': break;
case 'O': add(i, j, 2); add(j, i, 0); break;
case 'N': add(i, j, INF); add(j, i, 0); break;
}
}
int dfs(int x, int mini)
{
if (x == t || !mini) return mini;
int flow = 0;
for (int i = now[x]; i; i = e[i].next)
{
now[x] = i;
int k = e[i].to;
if (d[k] == d[x] + 1)
{
int tmp = dfs(k, min(mini, e[i].cap-e[i].flow));
if (tmp <= 0) continue;
e[i].flow += tmp;
e[i^1].flow -= tmp;
flow += tmp;
mini -= tmp;
if (!mini) break;
}
}
return flow;
}
bool bfs(int s, int t)
{
memset(flag, 0, sizeof flag);
memset(d, 0, sizeof d);
queue<int>q;
q.push(s);
d[s] = 0;
flag[s] = 1;
while(!q.empty())
{
int x = q.front();
q.pop();
for (int i = p[x]; i; i = e[i].next)
{
int k = e[i].to;
if (!flag[k] && e[i].cap > e[i].flow)
{
flag[k] = 1;
d[k] = d[x] + 1;
q.push(k);
}
}
}
return flag[t];
}
void dinic()
{
ans = 0;
while(bfs(s, t))
{
for (int i = 0; i <= t; ++i)
now[i] = p[i];
ans += dfs(s, INF);
}
}
int main()
{
freopen("bridge.in", "r", stdin);
freopen("bridge.out", "w", stdout);
while(scanf("%d %d %d %d %d %d %d", &n, &a1, &a2, &an, &b1, &b2, &bn) != EOF)
{
read();
s = 0, t = n + 1;
++a1, ++a2, ++b1, ++b2;
init();
add(s, a1, 2*an); add(a1, s, 0);
add(s, b1, 2*bn); add(b1, s, 0);
add(a2, t, 2*an); add(t, a2, 0);
add(b2, t, 2*bn); add(t, b2, 0);
dinic();
if (ans < 2 * (an+bn))
{
printf("No\n");
continue;
}
init();
add(s, a1, 2*an); add(a1, s, 0);
add(s, b2, 2*bn); add(b2, s, 0);
add(a2, t, 2*an); add(t, a2, 0);
add(b1, t, 2*bn); add(t, b1, 0);
dinic();
if (ans < 2 * (an+bn)) printf("No\n");
else printf("Yes\n");
}
return 0;
}