HDU 2544 典型的Dijkstra算法的应用

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544

先给Dijkstra算法的模板:

模板转自:http://www.cnblogs.com/mycapple/archive/2012/08/12/2634227.html

算法思路:

1、把所有结点分成两组:
      第一组:包括已经确定最短路径的结点;
      第二组:包括尚未确定最短路径的结点。
2、开始时,第一组只包含起点,第二组包含剩余的点;
3、用贪心的策略,按最短路径长度递增的顺序把第二组的结点加到第一组去,直到v0可达的所有结点都包含于第一组中。在这个过程中,不断更新最短路径,总保持从v0到第一组各结点的最短路径长度dist都不大于从v0到第二组任何结点的路径长度。
4、每个结点对应一个距离值,第一组结点对应的距离就是v0到此结点的最短路径长度,第二组结点对应的距离值就是v0由第一组结点到此结点的最短路径长度。
5、直到所有的顶点都扫描完毕(v0可达的所有结点都包含于第一组中),找到v0到其它各点的所有最短路径。

模板代码:

#include <iostream>
 using namespace std;
  
 const int maxnum = 100;
 const int maxint = 999999;
  
 // 各数组都从下标1开始
 int dist[maxnum];     // 表示当前点到源点的最短路径长度
 int prev[maxnum];     // 记录当前点的前一个结点
 int c[maxnum][maxnum];   // 记录图的两点间路径长度
 int n, line;             // 图的结点数和路径数
  
 void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])
 {
     bool s[maxnum];    // 判断是否已存入该点到S集合中
     for(int i=1; i<=n; ++i)
     {
         dist[i] = c[v][i];
         s[i] = 0;     // 初始都未用过该点
         if(dist[i] == maxint)
             prev[i] = 0;
         else
             prev[i] = v;
     }
     dist[v] = 0;
     s[v] = 1;
  
     // 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
     // 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
     for(int i=2; i<=n; ++i)
     {
         int tmp = maxint;
         int u = v;
         // 找出当前未使用的点j的dist[j]最小值
         for(int j=1; j<=n; ++j)
             if((!s[j]) && dist[j]<tmp)
             {
                 u = j;              // u保存当前邻接点中距离最小的点的号码
                 tmp = dist[j];
             }
         s[u] = 1;    // 表示u点已存入S集合中
  
         // 更新dist
         for(int j=1; j<=n; ++j)
             if((!s[j]) && c[u][j]<maxint)
             {
                 int newdist = dist[u] + c[u][j];
                 if(newdist < dist[j])
                 {
                     dist[j] = newdist;
                     prev[j] = u;
                 }
             }
     }
 }
  
 void searchPath(int *prev,int v, int u)
 {
     int que[maxnum];
     int tot = 1;
     que[tot] = u;
     tot++;
     int tmp = prev[u];
     while(tmp != v)
     {
         que[tot] = tmp;
         tot++;
         tmp = prev[tmp];
     }
     que[tot] = v;
     for(int i=tot; i>=1; --i)
         if(i != 1)
             cout << que[i] << " -> ";
         else
             cout << que[i] << endl;
 }
  
 int main()
 {
     freopen("input.txt", "r", stdin);
     // 各数组都从下标1开始
  
     // 输入结点数
     cin >> n;
     // 输入路径数
     cin >> line;
     int p, q, len;          // 输入p, q两点及其路径长度
  
     // 初始化c[][]为maxint
     for(int i=1; i<=n; ++i)
         for(int j=1; j<=n; ++j)
             c[i][j] = maxint;
  
     for(int i=1; i<=line; ++i)  
     {
         cin >> p >> q >> len;
         if(len < c[p][q])       // 有重边
         {
             c[p][q] = len;      // p指向q
             c[q][p] = len;      // q指向p,这样表示无向图
         }
     }
  
     for(int i=1; i<=n; ++i)
         dist[i] = maxint;
     for(int i=1; i<=n; ++i)
     {
         for(int j=1; j<=n; ++j)
             printf("%8d", c[i][j]);
         printf("\n");
     }
  
     Dijkstra(n, 1, dist, prev, c);
  
     // 最短路径长度
     cout << "源点到最后一个顶点的最短路径长度: " << dist[n] << endl;
  
     // 路径
     cout << "源点到最后一个顶点的路径为: ";
     searchPath(prev, 1, n);
 }
该题代码:

#include<iostream>
#include<stdio.h>
using namespace std;

const int maxnum = 103;
const int maxint = 100001;


 int dist[maxnum];     // 表示当前点到源点的最短路径长度
 int prev[maxnum];     // 记录当前点的前一个结点
 int c[maxnum][maxnum];   // 记录图的两点间路径长度
 int n,line;             // 图的结点数和路径数

 void Dijkstra(int n, int v)
 {
     bool s[maxnum]; //判断是否已存入该点到S集合中
     for(int i=1;i<=n;++i)
     {
      dist[i]=c[v][i];
      s[i]=0;// 初始都未用过该点
      if(dist[i]==maxint)
         prev[i]=0;
       else
         prev[i]=v;
     }
    dist[v]=0;
    s[v]=1;
     // 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
     // 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
     for(int i=2;i<=n;++i)
     {
      int tmp=maxint;
      int  u=v;
      // 找出当前未使用的点j的dist[j]最小值
      for(int j=1;j<=n;++j)
           if(!s[j]&&dist[j]<tmp)
           {
             u=j;// u保存当前邻接点中距离最小的点的号码
             tmp=dist[j];
           }
       s[u]=1;
       // 更新dist
       for(int j=1;j<=n;++j)
         if(!s[j]&&c[u][j]<maxint)
         {
              int newdist=dist[u]+c[u][j];
              if(newdist<dist[j])
              {
               dist[j]=newdist;
               prev[j]=u;
              }
         }
     }
 }
int main()
 {
    int  i,j;
    while(scanf("%d%d",&n,&line)&&(n||line))
    {
      int p,q,len;//输入p, q两点及其路径长度
       // 初始化c[][]为maxint
      for(i=1; i<=n; ++i)
         for(j=1; j<=n;++j)
             c[i][j] = maxint;

     for(i=1; i<=line; ++i)
     {
          scanf("%d%d%d",&p,&q,&len);
          //cin >> p >> q >> len;
          c[p][q] = len;      // p指向q
          c[q][p] = len;      // q指向p,这样表示无向图
     }

     for(i=1; i<=n; ++i)
         dist[i] = maxint;

       Dijkstra(n,1);

      printf("%d\n",dist[n]);
    }
 }


你可能感兴趣的:(ACM,dijkstra,算法模板)