How many ways??
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1565 Accepted Submission(s): 548
接下來的T行, 每行有三個整數 A, B, k, 表示問你從A 點到 B點恰好經過k個點的方案數 (k < 20), 可以走重複邊。如果不存在這樣的走法, 則輸出0
當n, m都爲0的時候輸入結束
非常巧妙的用矩陣的性質解決的問題,同時也是很裸的矩陣快速冪。
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#define INF 0x7fffffff
#define Matr 22
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
struct mat//矩陣結構體,a表示內容,size大小 矩陣從1開始
{
int a[Matr][Matr],size;
mat()
{
size=0;
memset(a,0,sizeof(a));
}
};
void print(mat m)//輸出矩陣信息,debug用
{
int i,j;
printf("%d\n",m.size);
for(i=0;i<m.size;i++)
{
for(j=0;j<m.size;j++)printf("%d ",m.a[i][j]);
printf("\n");
}
}
mat multi(mat m1,mat m2,int mod)//兩個相等矩陣的乘法,對於稀疏矩陣,有0處不用運算的優化
{
mat ans=mat(); ans.size=m1.size;
for(int i=1;i<=m1.size;i++)
for(int j=1;j<=m2.size;j++)
if(m1.a[i][j])//稀疏矩陣優化
for(int k=1;k<=m1.size;k++)
ans.a[i][k]=(ans.a[i][k]+m1.a[i][j]*m2.a[j][k])%mod;
return ans;
}
mat quickmulti(mat m,int n,int mod)//二分快速冪
{
mat ans=mat();
int i;
for(i=1;i<=m.size;i++)ans.a[i][i]=1;
ans.size=m.size;
while(n)
{
if(n&1)ans=multi(m,ans,mod);
m=multi(m,m,mod);
n>>=1;
}
return ans;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)&&n+m)
{
int x,y,k;
mat M;
M.size=n;
while(m--)
{
scanf("%d%d",&x,&y);
M.a[x+1][y+1]=1;
}
int q;
scanf("%d",&q);
while(q--)
{
scanf("%d%d%d",&x,&y,&k);
mat ans = quickmulti(M,k,1000);
printf("%d\n",ans.a[x+1][y+1]);
}
}
return 0;
}