邻接矩阵求路线数
特殊性在于周期,不过求下LCM还是可以搞的。
可以发现图是周期变化的,以12为一周期,于是建13个邻接矩阵,第13个为前12个的乘积,于是有G(K)=(G(13))^(k/12)*(G(1)*G(2)*……*G(k%12)),O(n^3*logk)
话说没注意邻接矩阵的含义WA了一次是闹哪样。。。。。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; const int N=50+5; const int p=1e4; int n; struct matrix{ ll a[N][N]; matrix(){memset(a,0,sizeof(a));} void clear(){memset(a,0,sizeof(a));} matrix operator * (const matrix &b)const{ static matrix ans; ans.clear(); for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) ans.a[i][j]+=a[i][k]*b.a[k][j]; for(int i=0;i<n;i++) for(int j=0;j<n;j++) ans.a[i][j]%=p; return ans; } matrix operator ^ (int k)const{ static matrix ans,b; ans.clear(); for(int i=0;i<n;i++)ans.a[i][i]=1; memcpy(b.a,a,sizeof(a)); for(;k;k>>=1,b=b*b)if(k&1)ans=ans*b; return ans; } }g[13]; bool can[13][N]; int u[N*N],v[N*N],pi[10]; int main(){ //freopen("a.in","r",stdin); int m,s,t,k; scanf("%d%d%d%d%d",&n,&m,&s,&t,&k); for(int i=1;i<=m;i++) scanf("%d%d",&u[i],&v[i]); int nfish; scanf("%d",&nfish); while(nfish--){ int T;scanf("%d",&T); for(int i=0;i<T;i++) scanf("%d",&pi[i]); for(int i=0;i<12;i++) can[i][pi[i%T]]=1; } for(int i=0;i<n;i++)can[12][i]=can[0][i]; for(int i=0;i<n;i++)g[0].a[i][i]=1; for(int i=1;i<=12;i++){ for(int j=1;j<=m;j++){ if(!can[i-1][u[j]]&&!can[i][v[j]]) g[i].a[u[j]][v[j]]++; if(!can[i-1][v[j]]&&!can[i][u[j]]) g[i].a[v[j]][u[j]]++; } g[0]=g[0]*g[i]; } g[0]=g[0]^(k/12); for(int i=1;i<=k%12;i++) g[0]=g[0]*g[i]; printf("%lld\n",g[0].a[s][t]); return 0; }