時隔幾個月重新做,終於ac了!
題目看似是圖論,但事實是矩陣相乘。根據離散數學書上說的,鄰接矩陣A的k次冪得到的新矩陣B中,bij表示ai到aj長度為k的通路數。
上面的方法計算的是任意兩點通路數,而本題目要求終點不能有出邊,基於醬紫,只要把終點那一行全部置為0就ok,這裡不求通路數,改為求能否k步到達終點。
#include <map>#include <set>#include <list>#include <queue>#include <deque>#include <stack>#include <string>#include <time.h>#include <cstdio>#include <math.h>#include <iomanip>#include <cstdlib>#include <limits.h>#include <string.h>#include <iostream>#include <fstream>#include <algorithm>using namespace std;#define LL long long#define MIN INT_MIN#define MAX INT_MAX#define PI acos(-1.0)#define FRE freopen("input.txt","r",stdin)#define FF freopen("output.txt","w",stdout)int N,M,T;typedef struct node{ int mat[30][30];}Mat;Mat unit,init;void Init(){ char c; scanf("%d%d",&N,&M); getchar(); int i,j,x1,y1,x2,y2,x3,y3,x4,y4; memset(init.mat,0,sizeof(init.mat));//每次清零! for(i=1; i<=N; i++) for(j=1; j<=M; j++) { scanf("((%d,%d),(%d,%d),(%d,%d),(%d,%d))",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4); getchar(); if ((i-1)*M+j == N*M) continue;//舍掉終點的出邊 init.mat[(i-1)*M+j][(x1-1)*M+y1]=1; init.mat[(i-1)*M+j][(x2-1)*M+y2]=1; init.mat[(i-1)*M+j][(x3-1)*M+y3]=1; init.mat[(i-1)*M+j][(x4-1)*M+y4]=1; unit.mat[(i-1)*M+j][(i-1)*M+j]=1; }}Mat mul(Mat a,Mat b){ int i,j,k; Mat c; for(i=1;i<=T;i++) for(j=1;j<=T;j++) { c.mat[i][j]=0; for(k=1;k<=T;k++)//一開始忘記了終點不能重複走,使到k==T c.mat[i][j] = c.mat[i][j]| (a.mat[i][k]&b.mat[k][j]); } return c;}Mat cal(int k)//矩陣二分快速冪{ Mat i=init,ans=unit; while (k) { if (k&1) ans=mul(ans,i); i=mul(i,i); k>>=1; } return ans;}int main(){ int t; scanf("%d",&t); bool ok = 0; while(t--) { Init();//input T=N*M; int num,q; scanf("%d",&num); //if (ok) puts(""); ok = 1; int i; while(num--) { scanf("%d",&q); Mat r=cal(q); if(r.mat[1][T]==0) printf("False\n"); else { for(i=1;i<=T;i++) { if(r.mat[1][i]) break; } if(i == T) printf("True\n"); else printf("Maybe\n"); } } puts(""); } return 0;}