图的存储有邻接矩阵,那么他就具备一些矩阵的性质,设有一个图的demo[100][100];那么demo[M][N]就是M—>N的距离,若经过一次松弛操作demo[M][N]=demo[M][K]+demo[K][N],即为demo[M][N]经过了两条条边的最小距离,floyd是 demo[M][N]=Min(demo[M][K]+demo[K][N],demo[M][N]),有可能两点之间直接距离最短,不经过第三边,那我们不考虑不经过两点之间的情况,那么demo[M][N]等于  demo[M][K]+demo[K][N] 枚举K的最小值,于是出现了一类问题,叫做两点之间经过N条边的最短距离,那么类比矩阵乘法,矩阵乘法是求和,我们在这里是求最小值,那么可以改造矩阵乘法得出,不是Floyd,K放在外面和里面没有区别,放外面像是Floyd,放里面就是标准的矩阵乘法,因为这个只用一次,所有对于枚举的状态是等价的。

  1. for(int k=; k<=cnt; k++)
  2. {
  3. for(int i=; i<=cnt; i++)
  4. {
  5. for(int j=; j<=cnt; j++)
  6. {
  7. c[i][j]=Min(a[i][k]+b[k][j],c[i][j]);
  8. }
  9. }
  10. }

每做一次类矩阵乘法,就代表将M,N松弛后多一条经过边,那么经过T次松弛后就会得到N,M经过T条边的最短距离,既然是类矩阵乘法,是不是遵循结合律呢?答案是的。对于矩阵,前面是经过T条边的最小值,后边是经过W条边的最小值,想乘代表经过了T+W条边的最小值,因为每进行一次都是插入一个点,即使点重复,那么他也会有环形出现,但还是经过了T+W条边,如此,我们可以利用矩阵快速幂求解其经过N条边之后的最小值,那么我们会发现矩阵跟图的是密不可分,一定还会有其他的特点去等待发现,它还可以用于求解图的生成树问题,下次更新。

本思想可以解决POJ3613,好像现在题没了,给一个网站https://www.acwing.com/problem/content/347/,代码附在下方。

  1. #include<iostream>
  2. #include<queue>
  3. #include<algorithm>
  4. #include<set>
  5. #include<cmath>
  6. #include<vector>
  7. #include<map>
  8. #include<stack>
  9. #include<bitset>
  10. #include<cstdio>
  11. #include<cstring>
  12. #define Swap(a,b) a^=b^=a^=b
  13. #define cini(n) scanf("%d",&n)
  14. #define cinl(n) scanf("%lld",&n)
  15. #define cinc(n) scanf("%c",&n)
  16. #define cins(s) scanf("%s",s)
  17. #define coui(n) printf("%d",n)
  18. #define couc(n) printf("%c",n)
  19. #define coul(n) printf("%lld",n)
  20. #define speed ios_base::sync_with_stdio(0)
  21. #define Max(a,b) a>b?a:b
  22. #define Min(a,b) a<b?a:b
  23. #define mem(n,x) memset(n,x,sizeof(n))
  24. #define INF 0x3f3f3f3f
  25. #define maxn 100010
  26. #define esp 1e-9
  27. #define mp(a,b) make_pair(a,b)
  28. using namespace std;
  29. const int N=;
  30. #define clr(a) memset(a,0,sizeof(a))
  31. int a[N][N],temp[N][N],ans[N][N];
  32. int used[*N];
  33. int p[*N];
  34. void floyed(int a[][N],int b[][N],int c[][N],int cnt)
  35. {
  36. for(int k=; k<=cnt; k++)
  37. {
  38. for(int i=; i<=cnt; i++)
  39. {
  40. for(int j=; j<=cnt; j++)
  41. {
  42. c[i][j]=Min(a[i][k]+b[k][j],c[i][j]);
  43. }
  44. }
  45. }
  46. }
  47. void copy(int n,int a[][N],int b[][N])
  48. {
  49. for(int i=; i<=n; i++)
  50. for(int j=; j<=n; j++)
  51. a[i][j]=b[i][j],b[i][j]=INF;
  52. }
  53. int solve(int s,int t,int n,int cnt)
  54. {
  55.  
  56. while(n)
  57. {
  58. if(n&)
  59. {
  60. floyed(ans,a,temp,cnt);
  61. copy(cnt,ans,temp);
  62. }
  63. floyed(a,a,temp,cnt);
  64. copy(cnt,a,temp);
  65. n>>=;
  66. }
  67. return ans[s][t];
  68. }
  69. int main()
  70. {
  71. int n,t,S,E;
  72. scanf("%d%d%d%d",&n,&t,&S,&E);
  73. int u,v,w;
  74. int cnt=;
  75. mem(ans,0x3f);
  76. mem(temp,0x3f);
  77. mem(a,0x3f);
  78. for(int i=; i<t; i++)
  79. {
  80. scanf("%d%d%d",&w,&u,&v);
  81. if(!used[u])
  82. {
  83. used[u]=;
  84. p[u]=++cnt;
  85. a[cnt][cnt]=temp[cnt][cnt]=ans[cnt][cnt]=;
  86. }
  87. if(!used[v])
  88. {
  89. used[v]=;
  90. p[v]=++cnt;
  91. a[cnt][cnt]=temp[cnt][cnt]=ans[cnt][cnt]=;
  92. }
  93. a[p[u]][p[v]]=a[p[v]][p[u]]=w;
  94. }
  95. printf("%d\n",solve(p[S],p[E],n,cnt));
  96. return ;
  97. }

这个题的边不连续,要先离散化。

疯子的算法总结(九) 图论中的矩阵应用 Part 1+POJ3613 Cow Relays的更多相关文章

  1. 疯子的算法总结(九) 图论中的矩阵应用 Part 2 矩阵树 基尔霍夫矩阵定理 生成树计数 Matrix-Tree

    定理: 1.设G为无向图,设矩阵D为图G的度矩阵,设C为图G的邻接矩阵. 2.对于矩阵D,D[i][j]当 i!=j 时,是一条边,对于一条边而言无度可言为0,当i==j时表示一点,代表点i的度. 即 ...

  2. 【算法】关于图论中的最小生成树(Minimum Spanning Tree)详解

    本节纲要 什么是图(network) 什么是最小生成树 (minimum spanning tree) 最小生成树的算法 什么是图(network)? 这里的图当然不是我们日常说的图片或者地图.通常情 ...

  3. 图论中最优树问题的LINGO求解

    树:连通且不含圈的无向图称为树.常用T表示.树中的边称为树枝,树中度为1的顶点称为树叶. 生成树:若T是包含图G的全部顶点的子图,它又是树,则称T是G的生成树. 最小生成树:设T=(V,E1)是赋权图 ...

  4. ZeroMQ接口函数之 :zmq_z85_decode – 从一个用Z85算法生成的文本中解析出二进制密码

    ZeroMQ 官方地址 :http://api.zeromq.org/4-0:zmq_z85_decode zmq_z85_decode(3)         ØMQ Manual - ØMQ/4.1 ...

  5. 相机标定:关于用Levenberg-Marquardt算法在相机标定中应用

    LM算法在相机标定的应用共有三处. (1)单目标定或双目标定中,在内参固定的情况下,计算最佳外参.OpenCV中对应的函数为findExtrinsicCameraParams2. (2)单目标定中,在 ...

  6. 算法效果AB测试中的PV-UV不对称性

    (转载请注明原创于潘多拉盒子) 算法效果的AB测试,是指在相同的应用场景下,对比不同算法的效果.通常的做法是,按照PV或UV随机分配流量到算法上,计算算法的CTR或转化率进行对比.为了表述简单,我们假 ...

  7. C++11新特性应用--介绍几个新增的便利算法(不更改容器中元素顺序的算法)

    总所周知.C++ STL中有个头文件,名为algorithm.即算法的意思. The header<algorithm>defines a collection of functions ...

  8. java排序算法(九):归并排序

    java排序算法(九):归并排序

  9. 机器学习、深度学习、和AI算法可以在网络安全中做什么?

    本文由  网易云发布. 本文作者:Alexander Polyakov,ERPScan的首席技术官和联合创始人.EAS-SEC总裁,SAP网络安全传播者. 现在已经出现了相当多的文章涉及机器学习及其保 ...

随机推荐

  1. python调用js

    安装 pip install PyExecJS 方法 eval() 输入参数:source(JS语句).cwd(路径) 返回值:result(语句执行结果) compile() 输入参数:source ...

  2. "字符反向拼接"组件:<reverse> —— 快应用组件库H-UI

     <import name="reverse" src="../Common/ui/h-ui/text/c_text_reverse"></ ...

  3. cmake添加版本号

    vVersion.cmake文件内容如下: #vversion.cmake #vDateTime string(TIMESTAMP vDateTime "%Y%m%d-%H%M%S" ...

  4. golang 在 Mac , Linux , Windows 下交叉编译详解

    一. 前言 Golang 支持交叉编译, 在一个平台上生成然后再另外一个平台去执行. 而且编译的工具[build]这个工具是Golang 内置的,不需要你去下载第三方的包啥的,贼方便. 二. 交叉编译 ...

  5. loadrunner vuser 限制修改

  6. 【Java】封装、继承、多态

    封装 在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装.隐藏起来的方法. 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代 ...

  7. 胜利大逃亡 BFS

    Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会. 魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius被关在(0 ...

  8. Matlab学习-(4)

    1. 函数 1.1 原始方法 之前我调用函数的方法是,首先写好函数文件,然后保存,然后在主函数中调用.这种方法的不足在于会导致你的工作目录的文件太多,从而导致很乱.在网上找了一些解决方法. 1.2 本 ...

  9. CentOS 使用中问题记录

    ⚠️使用yum提示Error: rpmdb open failed的解决方案 清除原rpmdb文件,这一步可能不用操作,直接进行第2步 # rm -f /var/lib/rpm/__db.* 重建rp ...

  10. Mysql列属性

    列属性又称之为字段属性在mysql中一共有6个属性:null,默认值(default),列描述(comment),主键(primary key),唯一键(unique key)和自动增长 修改数据库字 ...