最短路算法

常用的最短路算法有三种(Disjkstra,Floyd,Ballman-Floyd)

一、Disjkstra算法

Dijkstra算法要求图上的权非负数。同样使用于无向图;

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<stdio.h>  //HDU 2544  
  2.   
  3. #define maxsum 0x7fffffff   //重点  
  4. int map[101][101],dist[101],s[101];    
  5. void Dijkstra(int x,int n)  //x为起点,n为顶点个数    
  6.   
  7. {    
  8.     int mindis,u;    
  9.     for(int i=1;i<=n;i++)    
  10.     {    
  11.         dist[i]=map[x][i];    
  12.         s[i]=0;   //s集合为空  
  13.     }    
  14.     s[x]=1;   //s进入集合中  
  15.     for(int i=1;i<=n;i++)    
  16.     {    
  17.         mindis=maxsum;    
  18.         u=-1;    
  19.         for(int j=1;j<=n;j++)    
  20.         if(!s[j]&&dist[j]<mindis)//贪心算法,每次找出x通向?的最短路    
  21.         {    
  22.             u=j;    
  23.             mindis=dist[j];    
  24.         }    
  25.        s[u]=1;   //表明该路顶点进入集合s  
  26.         for(int j=1;j<=n;j++)    
  27.          if(s[j]==0)   //未进入s集合的点  
  28.             if(dist[u]+map[u][j]<dist[j]&&map[u][j]<maxsum) 对比直接到达的路和间接到达的路  权map[u][j]必须实际存在  
  29.             dist[j]=dist[u]+map[u][j];   //  
  30.     }    
  31. }    
  32. int main()    
  33. {    
  34.     int n,m,a,b,c;    
  35.    while(scanf("%d%d",&n,&m)!=EOF)    
  36.     {    
  37.        if(n==0&&m==0) break;    
  38.         while(~scanf("%d%d",&m,&n))    
  39.     {    
  40.         for(i=0;i<m;i++)    
  41.        {    
  42.             for(j=0;j<m;j++)    
  43.                 if(i==j)map[i][j]=0;   //impotant  
  44.                 else map[i][j]=maxsum;    
  45.         }    
  46.        for(i=0;i<n;i++)    
  47.         {    
  48.             scanf("%d%d%d",&a,&b,&c);    
  49.            if(c<map[a][b]) //可能有重边,就是说两点之间的path不唯一 //impotant   
  50.             map[a][b]=map[b][a]=c;    
  51.         }  
  52.   
  53.   
  54.             scanf("%d%d",&s,&e);s为起始点,e为终止点  
  55.         Dijkstra(s,n);   //需遍历所有顶点  
  56.         printf("%d\n",dist[e]);    
  57.    }    
  58.     return 0;    
  59. }  


 

二、Floyd算法

可以处理负权边,但无法处理负环,效率低,空间开销大,对于密集点图较为实用
本质是动态规划,要求图上没有负环,否则会导致死循环,可用于无向图,此时一个无向边相当于两个有向边

 

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<stdio.h>   //HDU 1874  
  2. #define MAX 99999999   //切忌max不能定义为0xfffffff,下面有两个map相加  
  3. int main()    
  4. {    
  5.     int i,j,k,n,m,x,y,a,b,c,map[201][201];    
  6.     while(~scanf("%d%d",&m,&n))    
  7.     {    
  8.         for(i=0;i<m;i++)    
  9.         {    
  10.             for(j=0;j<m;j++)    
  11.                 if(i==j)map[i][j]=0;    
  12.                 else map[i][j]=MAX;    
  13.         }    
  14.        for(i=0;i<n;i++)    
  15.         {    
  16.             scanf("%d%d%d",&a,&b,&c);    
  17.             if(c<map[a][b]) //可能有重边,就是说两点之间的path不唯一    
  18.             map[a][b]=map[b][a]=c;    
  19.        }    
  20.        scanf("%d%d",&x,&y);    
  21.        for(k=0;k<m;k++)   //k为“中转站”  
  22.        {    
  23.             for(i=0;i<m;i++)    
  24.                 for(j=0;j<m;j++)    
  25.                     if(map[i][j]>map[i][k]+map[k][j])//i到j的最短距离  
  26.                         map[i][j]=map[i][k]+map[k][j];    
  27.         }    
  28.        if(map[x][y]<MAX) printf("%d\n",map[x][y]);    
  29.         else printf("-1\n");    
  30.     }    
  31.     return 0;    
  32. }  


 

三、Bellman-Floyd算法

可以是负权值,可以判断是否为负环(非常好用)


 

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. include <iostream>  
  2. using namespace std;  
  3. const int maxnum = 100;  
  4. const int maxint = 99999;  
  5.    
  6. // 边,  
  7. typedef struct Edge{  
  8.  int u, v;    // 起点,重点  
  9.  int weight;  // 边的权值  
  10. }Edge;  
  11.    
  12. Edge edge[maxnum];     // 保存边的值  
  13. int  dist[maxnum];     // 结点到源点最小距离  
  14.    
  15. int nodenum, edgenum, source;    // 结点数,边数,源点  
  16.    
  17. // 初始化图  
  18. void init()  
  19. {  
  20.  // 输入结点数,边数,源点  
  21.  cin >> nodenum >> edgenum >> source;  
  22.  for(int i=1; i<=nodenum; ++i)  
  23.   dist[i] = maxint;  
  24.  dist[source] = 0;  
  25.  for(int i=1; i<=edgenum; ++i)  
  26.  {  
  27.   cin >> edge[i].u >> edge[i].v >> edge[i].weight;  
  28.   if(edge[i].u == source)          //注意这里设置初始情况  
  29.    dist[edge[i].v] = edge[i].weight;  
  30.  }  
  31. }  
  32.    
  33. // 松弛计算  
  34. void relax(int u, int v, int weight)  
  35. {  
  36.  if(dist[v] > dist[u] + weight)  
  37.   dist[v] = dist[u] + weight;  
  38. }  
  39.    
  40. bool Bellman_Ford()  
  41. {  
  42.          bool finish = true;    //  加个全部完成松弛的判断,优化了50多MS。  
  43.  for(int i=1; i<=nodenum-1; ++i)  
  44.               {bool finish = true;  
  45.   for(int j=1; j<=edgenum; ++j)  
  46.    {  
  47.                           relax(edge[j].u, edge[j].v, edge[j].weight);  
  48.                           finish=false;  
  49.                          }  
  50.                     if(finish)  
  51.                           break;  
  52.                 }  
  53.  bool flag = 1;  
  54.  // 判断是否有负环路  
  55.  for(int i=1; i<=edgenum; ++i)  
  56.   if(dist[edge[i].v] > dist[edge[i].u] + edge[i].weight)  
  57.   {  
  58.    flag = 0;  
  59.    break;  
  60.   }  
  61.  return flag;  
  62. }  
  63. int main()  
  64. {  
  65.  //freopen("input3.txt", "r", stdin);  
  66.     init();  
  67.  if(Bellman_Ford())  
  68.   for(int i = 1 ;i <= nodenum; i++)  
  69.    cout << dist[i] << endl;  
  70.  return 0;  
  71. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值