设有向图
D
=
<
V
,
E
>
,
V
=
{
v
1
,
v
2
,
…
,
v
n
}
D=<V,E>, V = \lbrace v_1,v_2, \ldots, v_n \rbrace
D=<V,E>,V={v1,v2,…,vn},令
a
i
j
(
1
)
a_{ij}^{(1)}
aij(1)顶点
v
i
v_i
vi邻接到顶点
v
j
v_j
vj的边的条数,称
(
a
i
j
(
1
)
)
n
×
n
(a_{ij}^{(1)})_{n \times n}
(aij(1))n×n为
D
D
D的邻接矩阵,简记为
A
A
A。
定理:
A
A
A的
l
l
l次幂
A
l
(
l
≥
1
)
A^l(l \geq 1)
Al(l≥1)中元素
a
i
j
(
l
)
a_{ij}^{(l)}
aij(l)为
D
D
D中
v
i
v_i
vi到
v
j
v_j
vj长度为
l
l
l的通路数。
对于此题,采用类邻接矩阵,只需记录
v
i
v_i
vi是否可以到达
v
j
v_j
vj,即边数为
1
1
1。
对于每次询问,跑矩阵快速幂判断即可。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct mat
{
ll a[50][50];
};
int szie;
mat A, B, V;
mat mat_mul(mat x, mat y)
{
mat res;
memset(res.a, 0, sizeof(res.a));
for(int i = 1; i <= szie; i++){
for(int j = 1; j <= szie; j++){
for(int k = 1; k <= szie; k++){
res.a[i][j] = (res.a[i][j] + x.a[i][k] * y.a[k][j]);
}
}
}
return res;
}
mat pow_matrix_mod(int n)
{
mat c = A, ans = V;
while(n){
if(n & 1) ans = mat_mul(ans, c);
c = mat_mul(c, c);
n >>= 1;
}
return ans;
}
int main()
{
int T, n, m;
cin >> T;
while (T--) {
memset(V.a, 0, sizeof(V.a));
memset(A.a, 0, sizeof(A.a));
memset(B.a, 0, sizeof(B.a));
scanf("%d %d", &n, &m);
getchar();
szie = n*m;
for (int i = 1; i <= szie; ++i) V.a[i][i] = 1;
int x1, y1, x2, y2, x3, y3, x4, y4;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
scanf("((%d,%d),(%d,%d),(%d,%d),(%d,%d))",&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4);
if (i == n && j == m) continue;
int p = (i-1)*m+j;
A.a[p][(x1-1)*m+y1] = 1;
A.a[p][(x2-1)*m+y2] = 1;
A.a[p][(x3-1)*m+y3] = 1;
A.a[p][(x4-1)*m+y4] = 1;
getchar();
}
}
int Q, l;
scanf("%d", &Q);
while (Q--) {
scanf("%d", &l);
B = pow_matrix_mod(l);
if (B.a[1][szie] == 0) cout << "False" << '\n';
else {
int flag = 0;
for (int i = 1; i < szie; ++i) {
if (B.a[1][i]) {
flag = 1;
break;
}
}
if (!flag) cout << "True" << '\n';
else cout << "Maybe" << '\n';
}
}
cout << '\n' ;
}
return 0;
}