最短路径(未完成)

来源:互联网 发布:小米怎么看网络制式 编辑:程序博客网 时间:2024/05/21 11:01

我们把带有权值的图称为带权图。(如图)


最短路径 - 区庆亮 - oql

        有四种算法可以有效地解决最短路径问题,但是,边的权值可以为负,出现负权值时,有一些方法不适用。

        下面介绍四种求最短路径的算法。

住:dis[u][v]为u,v的最短路径。w[u][v]为边的权值

   1 . Floyed-Warshall算法

     简称 Floyed(弗洛伊德)算法,时间复杂度为O(n^3),是最简单的最短路径算法。适用于出现负权值的情况。


    算法描述:


    (1)初始化:假如u,v两条边有相连的情况,那么dis [ u ] [ v ] =dis [ v ] [ u ] =w [ u ] [ v ] ;
    (2)for k=1 to n


           for i=1 to n


            for j=1 to n


              假如 i , j , k 互不相等 && dis[ i ] [ j ] > dis[ i ] [ k ] + dis[ j ] [ k ]


                dis[ i ] [ j ] = dis[ i ] [ k ] + dis[ j ] [ k ];


     (3)输出dis[ s ] [ e ];


    程序:


   



2.Dijkestra 算法


时间复杂度O(n^2),是一种单源最短路径。不适用于出现负权值的情况。


设起点为s,dis [ v ]为s,v的最短路径


算法描述:


(1)初始化:dis [ v ] =  ∞,dis [ s ] = 0;


(2)for i=1 to n


               for u,v


                    查找可以更新的点,记为k。


               for j=1 to n


                   dis [ k ] + w [ k ] [ j ] < dis [ j ] 


                     更新节点;


(3)算法结束,dis [ e ]为s,e的最短路;


程序:


#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
const int Maxx= 1 << 28;
double f[101][101];
int a[101][2];
double c[101];
bool b[101];
int i,j,n,m,s,e,minl,k,x,y;
int main()
{
 /*输入:可更改*/
 scanf("%d",&n);
 for(i=1;i<=n;i++) scanf("%d%d",&a[i][0],&a[i][1]);
 for(i=1;i<=n;i++) for(j=1;j<=n;j++) f[i][j]=Maxx;
 
 scanf("%d",&m);
 for(i=1;i<=m;i++)
 {
  
  scanf("%d%d",&x,&y);
  f[x][y]=f[y][x]=
  sqrt ( pow ( double (a[x][0]-a[y][0]) ,2) + pow ( double ( a[x][1]-a[y][1]) ,2) );
  
 }
 
 scanf("%d%d",&s,&e);
 for(i=1;i<=n;i++) c[i]=f[s][i];
 /*输入结束*/
 memset(b,0,sizeof(b));
 b[s]=1; c[s]=0;
 
 for(i=1;i<n;i++)
 {
  k=0; minl=Maxx;
  for(j=1; j<=n ;j++)
  if(!b[j] && (c[j]<minl))
  {
   
   k=j;
   minl=c[j];
   
  }
  if(k==0) break;
  b[k]=1;
  for(j=1;j<=n;j++)
  if(f[k][j]+c[k]<c[j]) c[j]=f[k][j]+c[k];
 }
 printf("%.2f",c[e]);
 return 0;
}


3.Bellman-Ford 算法

0 0