图的传递闭包算法,判断i与j是否有路径:

for (int k=1;k<=n;k++) //也可以说是Floyd的思想这是用邻接矩阵写的 
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
			if(can[i][k] && can[k][j])can[i][j]=1;

Floyd

计算图中每对顶点(任意两点)之间的最短路径 代码如下

Floyd1:

 for (int k=1;k<=n;k++)//遍历每对点 
 	for (int i=1;i<=n;i++) 
 		for (int j=1;j<=n;j++) 
 			if (d[i][k]+d[k][j]<d[i][j])d[i][j]=d[i][k]+d[k][j] 
 /*初始化条件: D[ i][ i ]=0  自己到自己为0 对角线为0;
D[i][j]=边权,i与j有直接相连的边
D[i][j]= +∞ ,i与j无直接相连的边。因为要找最小路径啊*/

Floyd2:

//设path[i][j] 记录i到j的最短路径中j的前驱顶点。
//初始化:i到j有边
path[i][j]:=i; 
path[j][i] :=j
for (int k=1;k<=n;k++)
 for (int i=1;i<=n;i++)
  for (int j=1;j<=n;j++)
              if (d[i][k]+d[k][j]<d[i][j] )
                     {
                      d[i][j]=d[i][k]+d[k][j];
                      path[i][j]=path[k][j]
                      }

Floyd3:

//初始化:
path[i][j]= -1: //i与j不通的
path[i][j]:=0; //从i到j的最短路径是直接到达的。开始有边的都直接到达。
Path[i][j]>0;//从i到j的最短路径要经过点path[i,j].
for (int k=1;k<=n;k++)
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
		       if  (d[i][k]+d[k][j]<d[i][j] )
		       {
		       	d[i][j]=d[i][k]+d[k][j];
                          path[i][j]=k;
                         }

dijkstra

计算某一顶点到其它所有顶点的最短路径
若在处理过程中,有两点x、y出现不符合“三角形定理”(若连接必定存在dis[x] + len[x][y] >= dis[y] )或者说出现松弛,则可改进一下:
if ( dis[x]+len[x][y] < dis[y] )dis[y] = dis[x]+len[x][y];
dis点x到s的最短距离 len是x,y的距离
d[i]:顶点i到start的最短距离。
具体思路:假设有两组集合1 集合2。若在处理过程中,有两点x、y出现不符合“三角形定理”()或者说出现松弛,则可改进一下: if ( dis[x]+len[x][y] < dis[y])dis[y] = dis[x]+len[x][y]; d[i]:顶点i到start的最短距离。 具体思路:假设有两组集合1 集合2。我们把集合一看成一个整体,或者说已经探查清楚的区域,把集合二看成未探知的区域,(战争迷雾 括弧笑)可以假设是离散的,因为要一个一个点录入。从集合二找出离集合一最近的点,并从集合二移到集合一,这次检查集合二,看集合二中的点在该点加入集合一后,离集合一的距离有没有变短。重复这个过程,直到集合二没有点。 代码如下:

void dijkstra(int st);
{   
	for (int i=1;i<=n;i++) dis[i]=a[st][i];
	memset(f,false,sizeof(f));
	f[st]=true; 
	dis[st]=0;
	for (int i=1;i<n;i++)   
	{ 
	         int min=1000000000, k=0;
	         for (int j=1;j<=n;j++)
	         if (!f[j] &&(dis[j]<min)) 
	         min=dis[j],k=j;
	         if (k==0)  return;  //已经找不到了。       
	         f[k]=true;  //把k加入集合1;
	         for (int j=1;j<=n;j++)  //三角形迭代,更新最短距离
	         if (!f[j] &&(dis[k]+a[k][j]<dis[j]))dis[j]=dis[k]+a[k][j];      
	}

思想正确,不保证粘贴正确
但是dijsktra不能有负权。因为有负权的话它就会不停的做松弛就像刷副本刷钱一样。

Bellman-ford

判断是否有负权
和dijsktra差不多不过加了一个松弛次数判断,如果进行了n次松弛,还可以再进行松弛,就说明有负权,因为遍历所有的边,只需要n次。具体代码我也懒的敲了
死宅日志——最短路径

spfa

Bellman-ford每次都要检查所有那边,但是如果上一次,x点到s的最短距离没有改变,那么这一次的检查就是多余的。所以我们只要检查刚被松弛过了的点就可以了。代码如下:
死宅日志——最短路径
用队列记录松弛过的地方。SPFA中一个点可能在出队列之后再次被放入队列,也就是一个点改进过其它的点之后,过了一段时间可能本身会再次被改进,于是再次用来改进其它的点,这样反复迭代下去。

相关文章:

猜你喜欢
  • 2021-12-19
  • 2021-09-26
  • 2021-10-16
  • 2021-07-07
相关资源
相似解决方案