Description
Alice和Bob居住在一个由N座岛屿组成的国家,岛屿被编号为0到N-1。某些岛屿之间有桥相连,桥上的道路是双
向的,但一次只能供一人通行。其中一些桥由于年久失修成为危桥,最多只能通行两次。Alice希望在岛屿al和a2之间往返an次(从al到a2再从a2到al算一次往返)。同时,Bob希望在岛屿bl和b2之间往返bn次。这个过程中,所有危桥最多通行两次,其余的桥可以无限次通行。请问Alice和Bob能完成他们的愿望吗?
Input
本题有多组测试数据。
每组数据第一行包含7个空格隔开的整数,分别为N、al、a2、an、bl、b2、bn。
接下来是一个N行N列的对称矩阵,由大写字母组成。矩阵的i行j列描述编号i一1和j-l的岛屿间的连接情况,若为“O”则表示有危桥相连:为“N”表示有普通的桥相连:为“X”表示没有桥相连。
|
Output
对于每组测试数据输出一行,如果他们都能完成愿望输出“Yes”,否则输出“No”。
Sample Input
4 0 1 1 2 3 1
XOXX
OXOX
XOXO
XXOX
4 0 2 1 1 3 2
XNXO
NXOX
XOXO
OXOX
XOXX
OXOX
XOXO
XXOX
4 0 2 1 1 3 2
XNXO
NXOX
XOXO
OXOX
Sample Output
Yes
No
数据范围
4<=N<50
O<=a1, a2, b1, b2<=N-1
1 <=an. b<=50
No
数据范围
4<=N<50
O<=a1, a2, b1, b2<=N-1
1 <=an. b<=50
HINT
Source
网络流。
那么关键就是如何建图。
这道题只需要根据图中说的建图就行了,很经典的一种建图方法。不多说了。
那么这道题的关键是在哪里呢?关键就是制作一遍会有问题。
比如从a1万一到不了a2,然而最终流到了b2,这样显然是不可行的。
那么我们可以把b1和b2反一下再做一遍,如果还是满流就可以了。
那么这道题就愉快的解决了。
代码:
#include <bits/stdc++.h>
#define N 110
#define M 100010
#define INF 0x7f7f7f7f
#define T 51
using namespace std;
struct Edge
{
int to, next, v;
}e[M];
int head[M], cur[M], a[N][N], h[N], q[N];
int cnt, flag;
int n, a1, a2, an, b1, b2, bn, ans;
void ins(int u, int v, int w)
{
e[++ cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
e[cnt].v = w;
}
void insert(int u,int v,int w)
{
ins(u, v, w);
ins(v, u, 0);
}
void build()
{
memset(head, 0, sizeof(head));
cnt = 1;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
if(a[i][j] == 1) insert(i, j, 2);
else if(a[i][j] == 2) insert(i, j, INF);
}
int dfs(int x, int f)
{
if(x == T) return f;
int w, used = 0;
for(int i = cur[x]; i; i = e[i].next)
{
if(e[i].v && h[e[i].to] == h[x] + 1)
{
w = f - used;
w = dfs(e[i].to,min(e[i].v,w));
e[i].v -= w;
if(e[i].v) cur[x] = i;
e[i ^ 1].v += w;
used += w;
if(used == f)return f;
}
}
if(used == 0) h[x] = -1;
return used;
}
int bfs()
{
int t = 0, w = 1;
for(int i = 0; i <= T; i ++)
h[i] = -1;
h[t] = 0;
q[t] = 0;
while(t != w)
{
int now = q[t];
t ++;
for(int i = head[now]; i; i = e[i].next)
if(e[i].v && h[e[i].to] == -1)
{
h[e[i].to] = h[now] + 1;
q[w ++] = e[i].to;
}
}
if(h[T] == -1) return 0;
else return 1;
}
void dinic()
{
while(bfs())
{
for(int i = 0; i <= T; i ++)
cur[i] = head[i];
ans += dfs(0, INF);
}
}
int main()
{
while(scanf("%d%d%d%d%d%d%d", &n, &a1, &a2, &an, &b1, &b2, &bn) != EOF)
{
memset(a, 0, sizeof(a));
a1 ++;
a2 ++;
b1 ++;
b2 ++;
flag = 0;
for(int i = 1; i <= n; i ++)
{
char ch[55];
scanf("%s",ch);
for(int j = 1; j <= n; j ++)
if(ch[j - 1] == 'O') a[i][j] = 1;
else if(ch[j - 1] == 'N') a[i][j] = 2;
}
build();
insert(0, a1, an * 2);
insert(a2, T, an * 2);
insert(0, b1, bn * 2);
insert(b2, T, bn * 2);
ans = 0;
dinic();
if(ans < 2 * (an + bn))flag = 1;
if(!flag)
{
build();
insert(0, a1, an * 2);
insert(a2, T, an * 2);
insert(0, b2, bn * 2);
insert(b1, T, bn * 2);
ans = 0;
dinic();
if(ans < 2 * (an + bn)) flag = 1;
}
if(flag)printf("No\n");
else printf("Yes\n");
}
return 0;
}