前言
图论题一直是硬伤...
题目
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
Sample Output
1
【数据范围】
100%的数据,满足 2 <= N <= 10 ; 1 <= T <= 1000000000
分析
正解:【矩阵快速幂】
具体见落谷:https://www.luogu.org/problemnew/solution/P4159
考试暴力12.5分代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=10,mod=2009;
char b[MAXN+5];
ll a[MAXN+5][MAXN+5];
ll n,t,ans;
void dfs(ll u,ll fa,ll dis)
{
if(u==n&&dis==t)
{
ans++;
ans%=mod;
return ;
}
if(dis>t)
return ;
for(int i=1;i<=n;i++)
if(a[u][i]&&i!=fa)
dfs(i,u,dis+a[u][i]);
}
int main()
{
scanf("%lld%lld",&n,&t);
for(int i=1;i<=n;i++)
{
scanf("%s",b+1);
for(int j=1;j<=n;j++)
a[i][j]=(ll)b[j]-'0';
}
dfs(1,0,0);
printf("%lld",ans%mod);
return 0;
}
//依然暴力...或许可以剪枝
AC代码
自己打的矩阵加速,好有成就感
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=100,mod=2009;
int n,m,t;
struct Matrix
{
int n,m;
int a[MAXN+5][MAXN+5];
Matrix(){memset(a,0,sizeof(a));}
void clear()
{
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
a[i][i]=1;
}
Matrix operator*(const Matrix& b)
{
Matrix r;
r.n=n;r.m=b.m;
for(int i=1;i<=r.n;i++)
for(int j=1;j<=r.m;j++)
for(int k=1;k<=m;k++)
{
r.a[i][j]+=a[i][k]*b.a[k][j];
r.a[i][j]%=mod;
}
return r;
}
Matrix operator^(int p)
{
Matrix r,x=*this;//x指当前这个结构体
r.n=n,r.m=m;
r.clear();
for(;p;p>>=1,x=x*x)//快速幂
if(p&1)
r=r*x;
return r;
}
}f;
int pos(const int &u,const int &i)
{
return u+i*n;
}
int main()
{
scanf("%d%d",&n,&t);
f.m=f.n=n*9;
int x;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=8;j++)
f.a[pos(i,j)][pos(i,j-1)]=1;
for(int j=1;j<=n;j++)
{
scanf("%1d",&x);
f.a[i][pos(j,x-1)]=1;
}
}
f=f^t;
printf("%d",f.a[1][n]);
return 0;
}