https://daniu.luogu.org/problem/show?pid=2151#sub 题目就是说我们不可以回走; 但是环还是可以的; 如果上次1->3 现在不可以直接3->1 但是过一会再再走是可以的; 所以我们把边变成2个点; 边与边链接的时候发现这种情况就不连,这不就好了嘛; 然后快速幂t-1次,因为这个是边; 然后现在要求所有S点连出的边到所有E点连入的边的方案; 这个就乱搞好了
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #define Ll long long using namespace std; struct cs{int to,nxt;}a[1000]; struct jv{ int n,m; int a[125][125]; jv(){memset(a,0,sizeof a);} }c,ans; int head[1000],ll=1; int n,m,t,x,y,S,E,sum; jv cheng(jv a,jv b){ jv c;c.n=a.n;c.m=b.m; for(int i=1;i<=c.n;i++) for(int k=1;k<=a.m;k++)if(a.a[i][k]) for(int j=1;j<=c.m;j++) c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%45989; return c; } jv ksm(int k){ jv ans=c; for(k--;k;k>>=1,c=cheng(c,c)) if(k&1)ans=cheng(ans,c); return ans; } void init(int x,int y){ a[++ll].to=y; a[ll].nxt=head[x]; head[x]=ll; } void make(){ c.n=c.m=ll; for(int i=2;i<=ll;i++) for(int k=head[a[i].to];k;k=a[k].nxt) if(i!=(k^1))c.a[i][k]++; ans.n=ans.m=ll; for(int k=head[S];k;k=a[k].nxt) ans.a[1][k]=1; } int main() { scanf("%d%d%d%d%d",&n,&m,&t,&S,&E);S++;E++; for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); x++;y++; init(x,y);init(y,x); } make(); ans=cheng(ans,ksm(t-1)); for(int i=2;i<=ll;i++) if(a[i].to==E)sum=(sum+ans.a[1][i])%45989; printf("%d",sum); }