BZOJ1875 [SDOI2009]HH去散步

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

 

 

本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!

 

题目链接:BZOJ1875

正解:矩乘快速幂

解题报告:

  考虑如果没有那个不能往回走的约束条件的话,就是建出矩阵,直接矩乘快速幂就好了。

  但是没有办法处理往回走的情况,因为我们不希望有走过去再走回来这种情况的发生,所以有一个比较巧妙的方法就是按边建矩阵,把每条边拆成$2$条然后同样的做法就好了。

  注意想清楚,应该是矩阵的$t-1$次方就好了。

 

//It is made by ljh2000
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <complex>
#include <bitset>
using namespace std;
typedef long long LL;
typedef long double LB;
const double pi = acos(-1);
const int MAXN = 22;
const int MAXM = 150;
const int mod = 45989;
int n,m,t,S,T,ecnt,first[MAXN],to[MAXM],next[MAXM],ans,B[MAXM],lin[MAXM];
struct Matrix{ int s[121][121]; }A,tmp,Kong;
struct edge{ int x,y; }e[MAXM];
inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; }
inline int getint(){
    int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
    if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
}

inline Matrix operator * (const Matrix &q,const Matrix &qq) {
	tmp=Kong;
	for(int i=0;i<=ecnt;i++)
		for(int j=0;j<=ecnt;j++)
			for(int k=0;k<=ecnt;k++)
				tmp.s[i][j]+=q.s[i][k]*qq.s[k][j]%mod,tmp.s[i][j]%=mod;
	return tmp;
}

inline void cheng(){
	for(int i=0;i<=ecnt;i++) lin[i]=0;
	for(int i=0;i<=ecnt;i++) {
		for(int j=0;j<=ecnt;j++) {
			lin[i]+=B[j]*A.s[j][i]%mod;
			lin[i]%=mod;
		}
	}
	for(int i=0;i<=ecnt;i++) B[i]=lin[i];
}

inline void fast_pow(int y){
	while(y>0) {
		if(y&1) cheng();
		A=A*A;
		y>>=1;
	}
}

inline void work(){
	n=getint(); m=getint(); t=getint(); S=getint()+1; T=getint()+1;
	memset(first,-1,sizeof(first)); ecnt=-1; int x,y;
	for(int i=1;i<=m;i++) {
		x=getint()+1; y=getint()+1;
		e[(i-1)<<1].x=x; e[(i-1)<<1].y=y;
		e[(i-1)<<1|1].x=y; e[(i-1)<<1|1].y=x;
		link(x,y); link(y,x);
	}

	for(int i=0;i<=ecnt;i++) {
		x=e[i].y;
		for(int j=first[x];j!=-1;j=next[j]) {
			if(j==(i^1)) continue;
			A.s[i][j]=1;
		}
	}

	for(int i=0;i<=ecnt;i++) if(e[i].x==S) B[i]=1;

	fast_pow(t-1);

	for(int i=0;i<=ecnt;i++) if(e[i].y==T) ans+=B[i],ans%=mod;
	printf("%d",ans);
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("1875.in","r",stdin);
	freopen("1875.out","w",stdout);
#endif
    work();
    return 0;
}
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。

  

posted @ 2017-03-25 10:34  ljh_2000  阅读(279)  评论(0编辑  收藏  举报