Dijkstra算法模板

Dijkstra算法是一种最短路径算法,用于计算一个节点到其它所有节点的最短路径,动态路由协议OSPF中就用到了Dijkstra算法来为路由计算最短路径。
算法本身并不是按照我们的正常思维习惯,我们一般会,从原点遍历所有与之相连的节点,找到最短路径,再从最短路径上的那个点遍历与之相连的所有其它点(原点除外),然后依次类推。这样做虽然可以算出一个树形,但是在大多数情况下,这种算法会产生很多次优路径,也就是说非最短路径。
Dijkstra算法的大概过程:
假设有两个集合或者说两个表,表A和表B
表A表示生成路径,表B表示最后确定的路径
1.从原点出发,遍历检查所有与之相连的节点,将原点和这些节点存放到表A中,并记录下两节点之间的代价。
2.将代价最小的代价值和这两节点移动到表B中(其中一个是原点)。
3.把这个节点所连接的子节点找出,放入到表A中,算出子节点到原点的代价
4.重复第二步和第三步直到表A为空。然后根据表B中的数据算出最优树。
维基百科中还有另一种说法,Dijkstra算法的输入包含了一个有权重的有向图G,以及G中的一个来源顶点S。 我们以V表示G中所有顶点的集合。 每一个图中的边,都是两个顶点所形成的有序元素对。(u,v)表示从顶点u到v有路径相连。 我们以E所有边的集合,而边的权重则由权重函数w: E → [0, ∞]定义。 因此,w(u,v)就是从顶点u到顶点v的非负花费值(cost)。 边的花费可以想像成两个顶点之间的距离。任两点间路径的花费值,就是该路径上所有边的花费值总和。 已知有V中有顶点s及t,Dijkstra算法可以找到s到t的最低花费路径(i.e. 最短路径)。 这个算法也可以在一个图中,找到从一个顶点s到任何其他顶点的最短路径。

Dijstra算法的基础操作是边的拓展:如果存在一条从u到v的边,那么从s到u的最短路径可以通过将边(u,v)添加到尾部来拓展一条从s到v的路径。这条路径的长度是d[u]+w(u,v)。如果这个值比目前已知的d[v]的值要小,我们可以用新值来替代当前d[v]中的值。拓展边的操作一直执行到所有的d[v]都代表从s到v最短路径的花费。这个算法经过组织因而当d[u]达到它最终的值的时候没条边(u,v)都只被拓展一次。

例如,对下图中的有向图,应用Dijkstra算法计算从源顶点1到其它顶点间最短路径的过程列在下表中。

Dijkstra算法模板_第1张图片

Dijkstra算法的迭代过程:

Dijkstra算法模板_第2张图片

最短路

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 22998    Accepted Submission(s): 9848


Problem Description
在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?

 

Input
输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
 

Output
对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
 

Sample Input
   
   
   
   
2 1 1 2 3 3 3 1 2 5 2 3 5 3 1 2 0 0
 

Sample Output
   
   
   
   
3 2
 

#include<iostream>
using namespace std;
#define INF 1000010
#define MaxN 10005
int map[MaxN][MaxN];
int dist[MaxN];
bool b[MaxN];
int n,m,s=0;
void diskstra()
{
    memset(b,0,sizeof(b));
    b[s]=1;
    int id,min;
    int i,t;
    t=n;
    for(i=0;i<n;i++)
        dist[i]=map[s][i];
    while(--t)
    {
        min=INF;
        for(i=1;i<n;i++)
            if(!b[i]&&dist[i]<min)
            {
                min=dist[i];
                id=i;
            }
            b[id]=1;
            for(i=1;i<n;i++)
                if(!b[i]&&dist[i]>dist[id]+map[id][i])
                    dist[i]=dist[id]+map[id][i];
    }
}
int main()
{
    int u,v,w;
    
    while(scanf("%d%d",&n,&m),(m||n))
    {
        
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                map[i][j]=INF;
                if(i==j)
                    map[i][j]=0;
            }
            for(i=0;i<m;i++)
            {
                scanf("%d%d%d",&u,&v,&w);
                map[u-1][v-1]=map[u-1][v-1]>w?w:map[u-1][v-1];
                     map[v-1][u-1]=map[u-1][v-1];

            }
            diskstra();
            printf("%d\n",dist[n-1]);
    }
    return 0;
}



你可能感兴趣的:(Dijkstra算法模板)