正题
题目链接:https://www.luogu.com.cn/problem/P2151
题目大意
nnn个点mmm条边的一张无向图,走过一条边后下一次就不能再走这条,求AAA到BBB之间有多少长度为ttt的路径。
解题思路
因为有不能再走同一条的限制,所以不能直接裸上矩乘,换一个状态考虑。设fif_ifi表示上次走到第iii条边的结尾处,那么这样就可以对于每条边特化转移了。
时间复杂度O((2m)3logt)O(\ (2m)^3\log t\ )O( (2m)3logt )
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=121,XJQ=45989;
ll n,m,t,A,B;
struct node{ll x,y;
}a[N*2];
struct matrix{ll a[N][N];
}f,ans,c;
matrix operator*(matrix &a,matrix &b){memset(c.a,0,sizeof(c.a));for(ll i=0;i<m;i++)for(ll j=0;j<m;j++)for(ll k=0;k<m;k++)(c.a[i][j]+=a.a[i][k]*b.a[k][j]%XJQ)%=XJQ;return c;
}
int main()
{scanf("%lld%lld%lld%lld%lld",&n,&m,&t,&A,&B);for(ll i=0;i<m;i++){scanf("%lld%lld",&a[i].x,&a[i].y);a[i+m].y=a[i].x;a[i+m].x=a[i].y;}m<<=1;for(ll i=0;i<m;i++)for(ll j=0;j<m;j++)if(a[i].y==a[j].x&&i%(m/2)!=j%(m/2))f.a[i][j]++;for(ll i=0;i<m;i++)if(a[i].x==A)ans.a[0][i]=1;t--;while(t){if(t&1)ans=ans*f;f=f*f;t>>=1;}ll answer=0;for(ll i=0;i<m;i++)if(a[i].y==B)(answer+=ans.a[0][i])%=XJQ;printf("%lld\n",answer);
}