设有向图 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
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;
}