1297: [SCOI2009]迷路
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1322 Solved: 938
[ Submit][ Status][ Discuss]
Description
windy在有向图中迷路了。 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1。 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间。
Input
第一行包含两个整数,N T。 接下来有 N 行,每行一个长度为 N 的字符串。 第i行第j列为'0'表示从节点i到节点j没有边。 为'1'到'9'表示从节点i到节点j需要耗费的时间。
Output
包含一个整数,可能的路径数,这个数可能很大,只需输出这个数除以2009的余数。
Sample Input
2 2
11
00
5 30
12045
07105
47805
12024
12345
Sample Output
1
852
性质:如果一张图的邻接矩阵只有0和1表示通与不通的话,
从s到t且中间经过n条边的方案数就是这个矩阵自乘n次后的(s, t)的数值
这题的边长度范围是0到9
那么只要将每个点拆成9个点就好了
首先这九个点连成一条直线(第j个点和第j+1个点连边)
如果点x到点y有条长度为k的边,那么x的第k个点和y的第一个点连条边就好
之后就直接矩阵快速幂
#include<stdio.h>
#include<string.h>
#define mod 2009
typedef struct
{
int i, a[105][105];
void init(int n)
{
memset(a, 0, sizeof(a));
for(i=1;i<=n;i++)
a[i][i] = 1;
}
}Matrix;
Matrix Jz;
int n, m;
Matrix Jzcf(Matrix p1, Matrix p2)
{
Matrix pe;
int i, j, k;
memset(pe.a, 0, sizeof(pe.a));
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
for(k=1;k<=n;k++)
pe.a[i][j] = (pe.a[i][j]+p1.a[i][k]*p2.a[k][j])%mod;
}
}
return pe;
}
Matrix Powto(Matrix x, int y)
{
Matrix ans;
ans.init(n);
while(y)
{
if(y%2==1)
ans = Jzcf(ans, x);
x = Jzcf(x, x);
y /= 2;
}
return ans;
}
int main(void)
{
int i, j, x;
while(scanf("%d%d", &n, &m)!=EOF)
{
memset(Jz.a, 0, sizeof(Jz.a));
for(i=1;i<=n;i++)
{
for(j=1;j<=8;j++)
Jz.a[(i-1)*9+j][(i-1)*9+j+1] = 1;
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%1d", &x);
if(x==0)
continue;
Jz.a[(i-1)*9+x][(j-1)*9+1] = 1;
}
}
n = n*9;
Jz = Powto(Jz, m);
printf("%d\n", Jz.a[1][n-8]);
}
return 0;
}