题目描述
给出一个 n * n 的邻接矩阵A.
A是一个01矩阵 .
A[i][j]=1表示i号点和j号点之间有长度为1的边直接相连.
求出从 1 号点 到 n 号点长度为k的路径的数目.
输入描述:
第1行两个数n,k (20 ≤n ≤ 30,1 ≤ k ≤ 10)
第2行至第n+1行,为一个邻接矩阵
输出描述:
题目中所求的数目
示例1
输入
4 2
0 1 1 0
1 0 0 1
1 0 0 1
0 1 1 0
输出
2
说明
样例如图:
第一条路径:1-2-4
第二条路径:1-3-4
思路:
离散数学的公式,矩阵自乘k次,a[1][n]表示从1到n经过k条边的路径个数
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<string>
#include<cstring>
using namespace std;
#define ll long long
#define lson l,m,k<<1
#define rson m+1,r,k<<1|1
const int N=40;
ll b[N];
int n;
struct Matrix{
ll a[N][N];
void init(){
memset(a,0,sizeof(a));
for(int i=1;i<=N;i++){
a[i][i]=1;
}
}
};
Matrix ans;
Matrix mul(Matrix a,Matrix b){
Matrix c;
memset(c.a,0,sizeof(c.a));
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
c.a[i][j]=0;
for(int k=1;k<=n;k++){
c.a[i][j]+=a.a[i][k]*b.a[k][j];
}
}
}
return c;
}
Matrix pow(Matrix a,int k){
ans.init();
while(k){
if(k&1)ans=mul(ans,a);
a=mul(a,a);
k>>=1;
}
return ans;
}
int main(){
int m;
scanf("%d%d",&n,&m);
Matrix b;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%lld",&b.a[i][j]);
}
}
b=pow(b,m);
printf("%lld\n",b.a[1][n]);
}