bzoj1875 [SDOI2009]HH去散步——矩阵快速幂
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1875
有个限制是不能走回头路,比较麻烦;
所以把矩阵中的元素设成边的经过次数,单向边之间就好转移了;
最后从单向边的经过次数得到点的路径方案数。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const mod=45989; int n,m,T,A,B,head[25],ct=1,tot; struct N{ int hd,to,next; N(int h=0,int t=0,int n=0):hd(h),to(t),next(n) {} }edge[125]; struct Matrix{ int a[125][125]; Matrix(){memset(a,0,sizeof a);}// Matrix operator * (const Matrix &y) const { Matrix x; for(int i=1;i<=ct;i++) for(int k=1;k<=ct;k++) for(int j=1;j<=ct;j++) (x.a[i][j]+=a[i][k]*y.a[k][j])%=mod; return x; } void init() { for(int i=1;i<=ct;i++)a[i][i]=1; } }tr,ans; Matrix operator ^ (Matrix x,int y) { Matrix ret; ret.init(); for(int i=y;i;i>>=1,x=x*x) if(i&1)ret=ret*x;//i 而不是 y!!! return ret; } void add(int x,int y){edge[++ct]=N(x,y,head[x]); head[x]=ct;} int main() { scanf("%d%d%d%d%d",&n,&m,&T,&A,&B); for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } for(int i=head[A];i;i=edge[i].next) ans.a[1][i]++; for(int i=2;i<=ct;i++)//2 for(int j=2;j<=ct;j++) if(edge[i].to==edge[j].hd && i!=(j^1)) tr.a[i][j]++;// ans=ans*(tr^(T-1)); for(int i=head[B];i;i=edge[i].next) (tot+=ans.a[1][i^1])%=mod; printf("%d",tot); return 0; }