給定一個有向圖,有n個點,m條邊。求A點到B點恰好經過k條邊的方案數(可走重複邊)。
這道題表面上是dp,dfs什麼的,但實際上是一道矩陣乘法加快速冪的裸題。爲什麼呢,其實是因爲矩陣乘法它那相乘的特殊。首先把有向圖轉換成鄰接矩陣X(可達矩陣),即如果x點能到達y點,那麼a[x][y]=1,如果x,y兩點之間不能到達,那麼a[x][y]=0。假設A矩陣爲X的平方,那麼A[i][j]=ΣX[i][k]*X[k][j],這其實就是乘法原理與加法原理的結合,那麼這個A矩陣的A[i][j]就表示着i到j經過了2條邊的方案數,懂了嗎。那麼經過k條邊,只需用快速冪將X平方k次就可以了,這題就解決了。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
struct node
{
int a[25][25];
node()
{
memset(a,0,sizeof(a));
}
};
int n;
node chengfa(node a,node b)
{
node c;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%1000;
}
}
}
return c;
}
int main()
{
int m,t;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0 && m==0)break;
node pre,ans;
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
pre.a[x+1][y+1]=1;
}
for(int i=1;i<=n;i++)ans.a[i][i]=1;
scanf("%d",&t);
while(t--)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
x++;y++;
node s=ans,ss=pre;
while(k>0)
{
if(k%2==1)s=chengfa(ss,s);
ss=chengfa(ss,ss);
k/=2;
}
printf("%d\n",s.a[x][y]%1000);
}
}
return 0;
}