3504: [Cqoi2014]危桥
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1165 Solved: 590
[ Submit][ Status][ Discuss]
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
No
数据范围
4<=N<50
O<=a1, a2, b1, b2<=N-1
1 <=an. b<=50
解题思路:
神题。。。 网上证明好像有问题。。
就是先建图,跑最大流,看ans是否是2*an+2*bn。
满足的话,将b1,b2交换再做,再判断,如果还满足就满足。
以后遇到这种题的话,实在不会证,就看看是否是满足对称性的,再考虑交换来做。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define inf 0x7fffffff
#define ll long long
#define T 51
using
namespace
std
;
bool
flag
;
int
n
,
a1
,
a2
,
an
,
b1
,
b2
,
bn
;
int
cnt
,
ans
;
int
h
[
55
]
,
q
[
55
]
;
int
mp
[
55
]
[
55
]
;
struct
data
{
int
to
,
next
,
v
;
}
e
[
100005
]
;
int
head
[
55
]
,
cur
[
55
]
;
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
(
mp
[
i
]
[
j
]
==
1
)
insert
(
i
,
j
,
2
)
;
else
if
(
mp
[
i
]
[
j
]
==
2
)
insert
(
i
,
j
,
inf
)
;
}
bool
bfs
(
)
{
int
t
=
0
,
w
=
1
;
for
(
int
i
=
0
;
i
<=
T
;
i
++
)
h
[
i
]
=
-
1
;
q
[
0
]
=
0
;
h
[
0
]
=
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
;
return
1
;
}
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
)
h
[
x
]
=
-
1
;
return
used
;
}
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
(
mp
,
0
,
sizeof
(
mp
)
)
;
flag
=
0
;
a1
++
;
a2
++
;
b1
++
;
b2
++
;
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'
)
mp
[
i
]
[
j
]
=
1
;
else
if
(
ch
[
j
-
1
]
==
'N'
)
mp
[
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
;
}