题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1875
注意的是路径不可以重复,所以这题把边看成点。每一条无向边拆成两条有向边。
令${F[t][i][j]}$表示从编号为$i$的边走到编号为$j$的边走了$t$步的边集个数。
${F[t][i][j]=sum f[i-1][i][k]*f[i-1][k][j]}$
这不就是矩乘的形式么,矩乘优化DP即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define maxn 10010 10 #define llg long long 11 #define SIZE 126 12 #define mod 45989 13 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 14 llg nn,m,A,B,last[maxn*10],t; 15 llg cnt=1; 16 struct MATRIX 17 { 18 llg mt[SIZE][SIZE]; 19 llg x,y; 20 void init(){memset(mt,0,sizeof(mt)); x=y=0;} 21 }ans,def; 22 23 struct edge 24 { 25 llg from,to,next,v; 26 }e[maxn*10]; 27 28 llg in_() 29 { 30 int x=0,f=1;char ch=getchar(); 31 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 32 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 33 return x*f; 34 } 35 36 inline MATRIX operator *(MATRIX a,MATRIX b) 37 { 38 MATRIX c; 39 for (llg i=0;i<=cnt;i++) for (llg j=0;j<=cnt;j++) c.mt[i][j]=0; 40 c.x=a.x; c.y=b.y; 41 for(int i=1;i<=a.x;i++) 42 for(int j=1;j<=b.y;j++) 43 for(int k=1;k<=a.y;k++) 44 c.mt[i][j]=(c.mt[i][j]+(a.mt[i][k])*(b.mt[k][j]))%mod; 45 return c; 46 } 47 48 void insert(llg v,llg u) 49 { 50 e[++cnt].to=v; e[cnt].from=u; e[cnt].next=last[u],last[u]=cnt; 51 e[++cnt].to=u; e[cnt].from=v; e[cnt].next=last[v],last[v]=cnt; 52 } 53 54 int main() 55 { 56 yyj("bzoj1875"); 57 cin>>nn>>m>>t>>A>>B; 58 for (llg i=1;i<=m;i++) insert(in_(),in_()); 59 MATRIX b; 60 b.init(); 61 def.x=def.y=ans.x=ans.y=b.x=b.y=cnt; 62 t--; 63 for (llg i=2;i<=cnt;i++) 64 for (llg j=2;j<=cnt;j++) 65 if (e[i].to==e[j].from && i!=(j^1)) b.mt[i][j]++; 66 for (llg i=1;i<=cnt;i++) ans.mt[i][i]=1; 67 for (llg i=t;i;i>>=1,b=b*b) 68 if (i&1) 69 ans=ans*b; 70 for (llg i=last[A];i;i=e[i].next) def.mt[1][i]++; 71 ans=def*ans; 72 llg sum=0; 73 for (llg i=last[B];i;i=e[i].next) sum+=ans.mt[1][i^1]; 74 cout<<sum%mod; 75 return 0; 76 }