How many ways??
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2939 Accepted Submission(s): 1125
接下來的T行, 每行有三個整數 A, B, k, 表示問你從A 點到 B點恰好經過k個點的方案數 (k < 20), 可以走重複邊。如果不存在這樣的走法, 則輸出0
當n, m都爲0的時候輸入結束
這裏說一個知識點,好像是離散數學的內容,然而老師並沒有講。
這種題先構造矩陣A,(i , j)表示從 i 到 j 有無路徑(有爲1,否則爲0)(注意此時的路徑是單向的)。
然後從 i 點到 j 點經過 k 個點(終點也算),的走法數量爲:求出A^k,然後A(i , j)的數值就是結果。
這道題就是這種方法,直接跑一個快速冪就出來了。
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
const int MOD=1000;
struct Matrix
{
int h,w;
LL m[22][22];
};
Matrix Matrix_multiply(Matrix a,Matrix b)
{
Matrix c;
c.h=a.h;
c.w=b.w;
CLR(c.m,0);
for(int i=0;i<a.h;i++)
{
for(int j=0;j<a.w;j++)
{
if(a.m[i][j]==0)
continue;
for(int k=0;k<b.w;k++)
c.m[i][k]=(c.m[i][k]+a.m[i][j]*b.m[j][k]%MOD)%MOD;
}
}
return c;
}
Matrix Quick(Matrix a,int n)
{
Matrix pre;
pre.h=pre.w=a.h;
CLR(pre.m,0);
for(int i=0;i<a.h;i++)
pre.m[i][i]=1;
while(n)
{
if(n&1)
pre=Matrix_multiply(pre,a);
n>>=1;
a=Matrix_multiply(a,a);
}
return pre;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)&&(n||m))
{
Matrix now;
now.h=now.w=n;
CLR(now.m,0);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
now.m[x][y]=1;
}
int k;
scanf("%d",&k);
while(k--)
{
Matrix ans;
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
ans=Quick(now,z);
printf("%lld\n",ans.m[x][y]);
}
}
return 0;
}