一道很玄学的矩阵乘法,平时我们构造的矩阵都是以点为基础,但是这样构造不能减去走过去再回来的情况,所以这道题用了一个非常玄学的以边为基础构造矩阵,构造矩阵时将一条无向边看成两条有向边,用了一条,另一条就不再用,用这个矩阵连乘t-1次,然后与与起点相连的边构造的矩阵相乘,最后统计与终点相连的边的值
update 18-07-26
发一份结构体版本的
//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int mod=45989;
const int M=250;
struct mtix
{
int x[M][M];
mtix(){memset(x,0,sizeof(x));}
}f,g;
int n,m,st,ed,t,cnt=2;
int v[M],head[M],nxt[M];
inline int read()
{
int x=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
inline void add(int a,int b)
{
nxt[cnt]=head[a];v[cnt]=b;head[a]=cnt++;
return ;
}
mtix mul(mtix a,mtix b)
{
mtix c;
for (int i=0;i<cnt;i++)
for (int j=0;j<cnt;j++)
for (int k=0;k<cnt;k++)
c.x[i][j]=(c.x[i][j]+a.x[i][k]*b.x[k][j])%mod;
return c;
}
void mpow(int y)
{
mtix ans;
for (int i=0;i<=cnt;i++) ans.x[i][i]=1;
for (;y;g=mul(g,g),y>>=1)
if (y&1) ans=mul(ans,g);
f=mul(f,ans);
int emm=0;
for (int i=2;i<cnt;i++)
if (v[i]==ed) emm=(emm+f.x[0][i])%mod;
cout<<emm;
return ;
}
int main()
{
n=read();m=read();t=read();st=read();ed=read();
for (int i=1;i<=m;i++)
{
int a=read(),b=read();
add(a,b);add(b,a);
}
for (int i=head[st];i;i=nxt[i]) f.x[0][i]=1;
for (int i=2;i<cnt;i++)
for (int k=head[v[i]];k;k=nxt[k])
if (i!=(k^1)) g.x[i][k]=1;
mpow(t-1);
return 0;
}
数组版本的
//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int mod=45989;
const int M=250;
int n,m,st,ed,t,cnt=2;
int a[M][M],b[M][M],c[M][M],e[M][M];
int v[M],head[M],nxt[M];
inline int read()
{
int x=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
inline void add(int a,int b)
{
nxt[cnt]=head[a];
v[cnt]=b;head[a]=cnt++;
return ;
}
inline void mul()
{
int d[M][M]={0};
for (int i=0;i<cnt;i++)
for (int j=0;j<cnt;j++)
for (int k=0;k<cnt;k++)
d[i][j]=(d[i][j]+c[i][k]*b[k][j])%mod;
memcpy(c,d,sizeof(d));
return ;
}
inline void muls()
{
int d[M][M]={0};
for (int i=0;i<cnt;i++)
for (int j=0;j<cnt;j++)
for (int k=0;k<cnt;k++)
d[i][j]=(d[i][j]+b[i][k]*b[k][j])%mod;
memcpy(b,d,sizeof(d));
return ;
}
inline void mut()
{
int d[M][M]={0};
for (int i=0;i<cnt;i++)
for (int j=0;j<cnt;j++)
for (int k=0;k<cnt;k++)
d[i][j]=(d[i][j]+a[i][k]*c[k][j])%mod;
memcpy(e,d,sizeof(d));
return ;
}
int main()
{
n=read();m=read();t=read();st=read();ed=read();
for (int i=1;i<=m;i++)
{
int a=read(),b=read();
add(a,b);add(b,a);
}
for (int i=head[st];i;i=nxt[i]) a[0][i]=1;//超级源点到所有点?
for (int i=2;i<cnt;i++)
for (int k=head[v[i]];k;k=nxt[k])
if (i!=(k^1)) b[i][k]=1;//不是同一条边再构造
for (int i=0;i<=cnt;i++) c[i][i]=1;
int y=t-1;
for (;y;muls(),y>>=1) if (y&1) mul();//连乘
mut();int emm=0;//与起点连着的
for (int i=2;i<cnt;i++)
if (v[i]==ed) emm=(emm+e[0][i])%mod;//统计方案
cout<<emm;
return 0;
}