[SDOI2009]HH去散步

题目描述

HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。

现在给你学校的地图(假设每条路的长度都是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径

输入输出格式

输入格式:

第一行:五个整数N,M,t,A,B。其中N表示学校里的路口的个数,M表示学校里的 路的条数,t表示HH想要散步的距离,A表示散步的出发点,而B则表示散步的终点。

接下来M行,每行一组Ai,Bi,表示从路口Ai到路口Bi有一条路。数据保证Ai != Bi,但 不保证任意两个路口之间至多只有一条路相连接。 路口编号从0到N − 1。 同一行内所有数据均由一个空格隔开,行首行尾没有多余空格。没有多余空行。 答案模45989。

输出格式:

一行,表示答案。

输入输出样例

输入样例#1:
4 5 3 0 0
0 1
0 2
0 3
2 1
3 2
输出样例#1:
4

说明

对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。

对于100%的数据,N ≤ 50,M ≤ 60,t ≤ 2^30,0 ≤ A,B

很容易往矩阵上面想

但是不能立刻返回,这看似无法用矩阵

其实可以点边互化,将点的连接转为边的连接,这样就可以排除非法情况

如果一条边终点于另一条边起点相同且不为一条边,那么这两条边连接

于是转为构建边的矩阵Mat

然后求出Matt-1

初始矩阵pre:以A为起点的边

答案:ans=pre*Matt-1,将∑ans[1][i]输出(i终点为B)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 int Mod=45989;
 8 struct Node
 9 {
10   int u,v;
11 }edge[121];
12 struct Matrix
13 {
14   ll a[121][121];
15 }ans,pre,Mat;
16 int tot,n,m,A,B,t;
17 ll zyys;
18 Matrix operator*(const Matrix &x,const Matrix &y)
19  {int i,j,k;
20     Matrix res;
21     memset(res.a,0,sizeof(res.a));
22     for (i=0;i<=tot;i++)
23       {
24     for (j=0;j<=tot;j++)
25       {
26         for (k=0;k<=tot;k++)
27           {
28         res.a[i][j]+=x.a[i][k]*y.a[k][j];
29         res.a[i][j]%=Mod;
30           }
31       }
32       }
33     return res;
34   }
35 Matrix qpow(int x)
36 {int i;
37   Matrix res;
38   memset(res.a,0,sizeof(res.a));
39   for (i=0;i<=tot;i++)
40     res.a[i][i]=1;
41   while (x)
42     {
43       if (x&1) res=res*Mat;
44       Mat=Mat*Mat;
45       x/=2;
46     }
47   return res;
48 }
49 int main()
50 {int u,v,i,j;
51   cin>>n>>m>>t>>A>>B;
52   A++;B++;
53   tot=-1;
54   for (i=1;i<=m;i++)
55     {
56       scanf("%d%d",&u,&v);
57       u++;v++;
58       ++tot;
59       edge[tot].u=u;edge[tot].v=v;
60       ++tot;
61       edge[tot].v=u;edge[tot].u=v;
62     }
63   for (i=0;i<=tot;i++)
64     {
65       for (j=0;j<=tot;j++)
66     if (i!=j&&((i^1)!=j)&&edge[i].v==edge[j].u)
67     {
68       Mat.a[i][j]=1;
69     }
70     }
71   for (i=0;i<=tot;i++)
72     if (edge[i].u==A)
73       pre.a[1][i]=1;
74   ans=qpow(t-1);
75   ans=pre*ans;
76   for (i=0;i<=tot;i++)
77     if (edge[i].v==B)
78       {
79     zyys+=ans.a[1][i];
80     zyys%=Mod;
81       }
82   cout<<zyys;
83 }

 

posted @ 2017-10-12 14:53  Z-Y-Y-S  阅读(189)  评论(0编辑  收藏  举报