[BZOJ1975]HH去散步 图论+矩阵


题目大意

要求出在一个m条边,n个点的图中,相邻两次走的边不能相同,求在t时间时从起点A走到终点B的路径方案总数。将答案mod45989

输入格式:

第一行:五个整数N,M,t,A,B。

后面的m行,每行有两个数\(a_i\) \(b_i\),表示路口\(a_i\) \(b_i\)有有一条边。

输出格式:

一个整数,表示答案。

输入输出样例

input

4 5 3 0 0

0 1

0 2

0 3

2 1

3 2

output

4

Hint

对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。 对于100%的数据,N ≤ 20,M ≤ 60,t ≤ 2^30,0 ≤ A,B


解题分析

题目问你路径的方案总数,首先就想到要用矩阵+floyd的算法来求。

我们根据floyd的原理可以知道\(L[i][j]=\sum\limits_{k=1}^{n}L[i][k]*L[k][j]\)

所以我们可以建立一个矩阵 \(g[i][j]\)代表有一条从i到j的比。将这个矩阵幂t次,\(g[i][j]\)就代表i到j的走t条边的方案数。

因为这一题相邻两次走的边不能相同,所以我们就将边变成点来求方案数。

那么怎么统计答案呢?我们可以有一个转移矩阵2m2m,其中\(f[i][j]\)代表第i条边(原图中)的起点与第j条边(原图中)是一个点(且ij不能是同一条边),就代表点(新图)i与点(新图)j是相连的。答案矩阵是一个12m的矩阵,\(ans[1][i]\)代表第i(原图)条边的终点为题目给的A.把ans与自乘t次的F矩阵相乘。然后

 $$\sum ans[1][i](i代表终点为B的点(原图的边))$$就是答案。

其实我们可以理解为,ans就是加了一个虚点,代表着一个与所有起点为A的点(原图中的边)相连的点。乘后的ans代表这个虚点到所以点的方案。我们只要统计终点为B的点的方案数就可以了。

代码自带大常数==!

  1. #include <stdio.h>
  2. #include <iostream>
  3. #include <cmath>
  4. #include <queue>
  5. #include <algorithm>
  6. #include <cstring>
  7. #include <climits>
  8. #include <cstdlib>
  9. #define MAXN (60+10)*2
  10. #define max(a,b) (a>b?a:b)
  11. #define min(a,b) (a<b?a:b)
  12. using namespace std;
  13. int mod=45989,n,m,a,b,t,num,head[MAXN],tot,tail[MAXN],M;
  14. struct Edge{
  15. int next,to,from,next1;
  16. }edge[MAXN<<1];
  17. void add(int from,int to)
  18. {
  19. edge[++num].next=head[from];
  20. edge[num].next1=tail[to];
  21. edge[num].to=to;
  22. edge[num].from=from;
  23. head[from]=num;
  24. tail[to]=num;
  25. }
  26. struct matrix{
  27. int n,m;
  28. int data[MAXN][MAXN];
  29. void print()
  30. {
  31. for(int i=1;i<=n;i++)
  32. {
  33. for(int j=1;j<=m;j++)
  34. printf("%d ",data[i][j]);
  35. printf("\n");
  36. }
  37. }
  38. matrix operator * (matrix b)
  39. {
  40. matrix ans;
  41. memset(ans.data,0,sizeof(ans.data));
  42. ans.n=n;ans.m=b.m;
  43. for(int i=1;i<=ans.n;i++)
  44. for(int j=1;j<=ans.m;j++)
  45. for(int k=1;k<=ans.m;k++)
  46. ans.data[i][j]+=(data[i][k]*b.data[k][j])%mod,ans.data[i][j]%=mod;
  47. return ans;
  48. }
  49. void too(matrix b)
  50. {
  51. n=b.n;m=b.m;
  52. for(int i=1;i<=n;i++)
  53. for(int j=1;j<=m;j++)
  54. data[i][j]=b.data[i][j];
  55. }
  56. }f,ans,zero,pf;
  57. void power(int k)
  58. {
  59. if(k==1) pf=f;
  60. else
  61. {
  62. power(k/2);
  63. if(k%2==1) pf=pf*pf,pf=pf*f;
  64. else pf=pf*pf;
  65. }
  66. }
  67. int main()
  68. {
  69. scanf("%d%d%d%d%d",&n,&m,&t,&a,&b);
  70. for(int i=1;i<=m;i++)
  71. {
  72. int x,y;
  73. scanf("%d%d",&x,&y);
  74. add(x,y);
  75. add(y,x);
  76. }
  77. f.n=f.m=2*m;ans.n=1;ans.m=2*m;M=2*m;
  78. for(int i=head[a];i;i=edge[i].next) ans.data[1][i]=1;
  79. for(int s=0;s<n;s++)
  80. for(int i=head[s];i;i=edge[i].next)
  81. for(int j=head[edge[i].to];j;j=edge[j].next)
  82. if((i+1)!=((j+1)^1))
  83. {
  84. f.data[i][j]++;
  85. }
  86. power(t-1);ans=ans*pf;
  87. for(int i=tail[b];i;i=edge[i].next1)
  88. tot=(tot+ans.data[1][i])%mod;
  89. printf("%d\n",tot);
  90. return 0;
  91. }

[BZOJ1975]HH去散步 图论+矩阵的更多相关文章

  1. BZOJ_1875_[SDOI2009]HH去散步_矩阵乘法

    BZOJ_1875_[SDOI2009]HH去散步_矩阵乘法 Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时H ...

  2. BZOJ-1875 HH去散步 DP+矩阵乘法快速幂

    1875: [SDOI2009]HH去散步 Time Limit: 20 Sec Memory Limit: 64 MB Submit: 1196 Solved: 553 [Submit][Statu ...

  3. BZOJ 1875: [SDOI2009]HH去散步( dp + 矩阵快速幂 )

    把双向边拆成2条单向边, 用边来转移...然后矩阵乘法+快速幂优化 ------------------------------------------------------------------ ...

  4. 【SDOI2009】HH去散步(矩阵快速幂)

    题面 题目描述 HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因为HH是 ...

  5. 1875. [SDOI2009]HH去散步【矩阵乘法】

    Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又 ...

  6. [BZOJ 1875] [SDOI 2009] HH去散步【矩阵乘法】

    题目链接:BZOJ - 1875 题目分析: 这道题如果去掉“不会立刻沿着刚刚走来的路走回”的限制,直接用邻接矩阵跑矩阵乘法就可以了.然而现在加了这个限制,建图的方式就要做一些改变.如果我们把每一条边 ...

  7. BZOJ 1875: [SDOI2009]HH去散步(矩阵乘法)

    首先,题意就把我们引向了矩阵乘法,注意边长m<=60,那么就按边建图,变成一个120个点的图,然后乱搞就行了。 PS:WA了N久改了3次终于A了QAQ CODE: #include<cst ...

  8. BZOJ.1875.[SDOI2009]HH去散步(DP 矩阵乘法)

    题目链接 比较容易想到用f[i][j]表示走了i步后到达j点的方案数,但是题目要求不能走上一条走过的边 如果这样表示是不好转移的 可以考虑边,f[i][j]表示走了i步后到达第j条边的方案数,那么有 ...

  9. [SDOI2009]HH去散步 「矩阵乘法计数」

    计数问题也许可以转化为矩阵乘法形式 比如若该题没有不能在一条边上重复走的条件限制,那么直接将邻接矩阵转化为矩阵乘法即可 故 矩阵乘法计数 对于计数问题,若可以将 \(n\) 个点表示成 \(n \ti ...

随机推荐

  1. mysql基础综述(四)

    1.数据库的简单介绍 1.1 数据库,就是一个文件系统,使用标准sql对数据库进行操作 1.2 常见的数据库 oracle  是oracle公司的数据库,是一个收费的大型的数据库 DB2,是IBM公司 ...

  2. sql不显示反复列

    在报表里,基本上都能够把反复的资料不显示,在SQL里怎么才干做到例如以下情况呢? a 10 a 20 b 30 b 40 b 50 显示为: a 10 20 b 30 40 50 SQL 例如以下: ...

  3. Geeks - Range Minimum Query RMQ范围最小值查询

    使用线段树预处理.能够使得查询RMQ时间效率在O(lgn). 线段树是记录某范围内的最小值. 标准的线段树应用. Geeks上仅仅有两道线段树的题目了.并且没有讲到pushUp和pushDown操作. ...

  4. 初学ToggleButton 点击button,更换button背景图片;再次点击,恢复之前背景图

    上方的图标,R.drawable.register_checked  是选中图片 下方的图标,   R.drawable.register_unchecked 是未选中图片 默认是上方的选中效果.点击 ...

  5. dnscapy使用——本质上是建立ssh的代理(通过dns tunnel)

    git clone https://github.com/cr0hn/dnscapy.git easy_install Scapy 服务端: python dnscapy_server.py a.fr ...

  6. [JavaEE] Maven简介

    转载自:百度 http://baike.baidu.com/view/336103.htm?fr=aladdin 一.简介 Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构 ...

  7. SQL 数据库性能优化

    http://blog.csdn.net/yzllz001/article/details/54848513 1.  减少数据访问(减少磁盘访问) 2.  返回更少数据(减少网络传输或磁盘访问) 3. ...

  8. Redis学习笔记(三) 基本命令:Key操作

    参考:http://doc.redisfans.com/ del key 删除给定的一个或多个Key(多个key用空格隔开),删除成功返回1,当key不存在时,返回0:例:del no-exist-k ...

  9. linux中openssl生成证书和自签证书

    1.首先要生成服务器端的私钥(key文件): 命令: openssl genrsa -des3 -out server.key 1024 运行时会提示输入密码,此密码用于加密key文件(参数des3便 ...

  10. 基础apache命令

    在启动Apache服务之前,可以使用下面的命令来检查配置文件的正确性. C:\Apache2.2\bin> httpd  -n  Apache2.2  -t 还可以通过命令行控制Apache服务 ...