题意描述:
给定一张无向图,一个起点一个终点。
定义一条合法路径为不存在任何一条满足A->B->A的关系的子路径。
求从起点到终点长为一个值的路径数。
数据范围:
对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。
对于100%的数据,N ≤ 20,M ≤ 60,t ≤ 2147483647,0 ≤ A,B<=N-1。
解法:
30分做法:用队列维护走过当前长度到达的点,拓展转移可行转移。当长度达到定值的时候,若达到终点,则答案加一。
复杂度:最劣
O(nt)
100分做法:
由于转移次数较多,很自然的想到可以利用矩阵表示转移,用快速幂进行优化。
问题在于,如何用一个矩阵表示一系列转移?
用一个数列表示当前走到每个点的方案数。这些数在一步操作后会发生复杂的转移,累加到其他格子里面去,这正是矩阵所支持的。
若没有合法路径的限制?
最直观的想法是,在矩阵中,一行表示当前点被转移的来源。若存在j->i的路径,则
ai,j=1
。
这样乘上一个矩阵就表示进行了一次全部的转移。
如果加上路径的限制条件呢?
相当于只能“向前走”。可惜,点是不具有方向性的,所以我们把转移对象选择为边。边可以分成两条,分别为u->v和v->u,而按照这个想法,如果存在v->k,则边u->v可以向v->k转移。按照这个想法我们就重新建立了一个合法的矩阵。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define R register
#define mod 45989
#define ll long long
using namespace std;
struct new_node{int a,b;}node[125];
int n,m,kk,A,B;
int nt;
int bs[125];
int read()
{
R int xx;R char ch;
while(ch=getchar(),ch<'0'||ch>'9');xx=ch-'0';
while(ch=getchar(),ch>='0'&&ch<='9')xx=xx*10+ch-'0';
return xx;
}
struct MAT
{
int a[123][123];
inline MAT operator * (const MAT &f)const
{
R MAT ret;
R int i,j,k;
for(i=0;i<=nt;++i)
for(j=0;j<=nt;++j)
{
ret.a[i][j]=0;
for(k=0;k<=nt;++k)
ret.a[i][j]=(ret.a[i][j]+a[i][k]*f.a[k][j])%mod;
}
return ret;
}
}v0,v1,ans;
void pow(int k)
{
R MAT base=v1;
ans=v0;
while(k)
{
if(k&1)ans=ans*base;
base=base*base;k>>=1;
}
}
void build()
{
R int i,j,x,y;
memset(v0.a,0,sizeof(v0.a));
memset(v1.a,0,sizeof(v1.a));
memset(bs,0,sizeof(bs));
nt=-1;
for(i=1;i<=m;++i)
{
x=read(),y=read();
node[++nt]=(new_node){x,y};
node[++nt]=(new_node){y,x};
}
for(i=0;i<=nt;++i)
{
for(j=0;j<=nt;++j)
{
if(node[i].a==node[j].b&&i!=(j^1))
v1.a[i][j]=1;
}
}
for(i=0;i<=nt;++i)v0.a[i][i]=1;
}
void print()
{
int sum=0;
R int i,e;
for(i=0;i<=nt;++i)
if(node[i].a==A)
bs[i]=1;
for(e=0;e<=nt;++e)
if(node[e].b==B)
{
for(i=0;i<=nt;++i)
sum=(sum+(ll)bs[i]*ans.a[e][i])%mod;
}
printf("%d",sum);
}
int main()
{
n=read(),m=read(),kk=read(),A=read(),B=read();
build();pow(kk-1);print();
return 0;
}
/*
void show()
{
printf("begin:\n");
R int i,j;
for(i=0;i<=nt;++i,printf("\n"))
for(j=0;j<=nt;++j)
printf("%d ",a[i][j]);
printf("end\n");
}
*/