洛谷 P4159 [SCOI2009]迷路
windy在有向图中迷路了。 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1。 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间。
根据题意,可以写出转移方程
fi,j=∑fr,j−w[r]
fi,j表示第j时刻在第i个点时的方案数,r为i的前驱,w[r]为距离
而T≤109,所以肯定是不可行的,就要用到矩阵加速
如果对于上面那个转移方程是无法矩阵加速的
但是边权只有1…9,我们可以把j分开表示,也就是把所有距离的情况都表示出来
那么对于上面的那个转移方程就有两种转移形式
-
这个距离j不是真正的距离,那么fr,j可以从fr,j−1继承
-
这个j是真正的距离,那么fr,j对fi,j是有贡献的
代码和拆点一样= =
Code
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n,t,d[500][500],s[500][500],b[500][500],p=2009;
char ch;
void jzc(int x[500][500],int y[500][500])
{
for (int i=1;i<=n*9;i++)
for (int j=1;j<=n*9;j++)
for (int k=1;k<=n*9;k++)
b[i][j]=(b[i][j]+x[i][k]*y[k][j]%p)%p;
for (int i=1;i<=n*9;i++)
for (int j=1;j<=n*9;j++)
x[i][j]=b[i][j],b[i][j]=0;
}
int main()
{
cin>>n>>t;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=8;j++) //第一个的继承关系
d[i+j*n][i+(j-1)*n]=1;
for (int j=1;j<=n;j++)
{
cin>>ch;
d[i][j+n*((ch-'0')-1)]=1; //真正的边
}
}
for (int i=1;i<=n*9;i++)
s[i][i]=1;
while (t)
{
if (t&1)jzc(s,d);
jzc(d,d);
t>>=1;
}
cout<<s[1][n]<<endl;
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步