zoukankan      html  css  js  c++  java
  • Dijkstra算法

    定义
    ( Dijkstra算法一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的方式,这里均采用永久和临时标号的方式。注意该算法要求图中不存在负权边。 )
    原理
    ( 1.首先,引入一个辅助数组(vector)D,它的每个元素D[i]表示当前所找到的从起始点(即源点v)到其它每个顶点v_i的长度。 \ 例如,D[3]=2表示从起始点到顶点3的路径相对最小长度为2。这里强调相对就是说在算法执行过程中D的值是在不断逼近最终结果但在过程中不一定就等于长度。 \ 2.D的初始状态为:若从v到v_i有弧(即从v到v_i存在连接边),则D 为弧上的权值(即为从v到v_i的边的权值);否则置D[i]为∞。 \ 显然,长度为D[j]=Min{D|v_i∈V}的路径就是从v出发到顶点v_j的长度最短的一条路径,此路径为(v,v_j)。 \ 3.那么,下一条长度次短的是哪一条呢?也就是找到从源点 到下一个顶点的最短路径长度所对应的顶点,且这条最短路径长度仅次于从源点v到顶点v_j的最短路径长度。 \ 假设该次短路径的终点是v_k,则可想而知,这条路径要么是(v,v_k),或者是(v,v_j,v_k)。它的长度或者是从v到v_k的弧上的权值,或者是D[j]加上从v_j到v_k的弧上的权值。 \ 4.一般情况下,假设S为已求得的从源点v出发的最短路径长度的顶点的集合,则可证明:下一条次最短路径(设其终点为x)要么是弧(v,x),或者是从源点 出发的中间只经过S中的顶点而最后到达顶点x的路径。 \ 因此,下一条长度次短的的最短路径长度必是D[j]=Min{D[i]|∈V-S},其中D 要么是弧( )上的权值,要么是D[k](v_k∈S)和弧(v_k,v_i)上的权值之和。 \ 算法描述如下: \ 1)令arcs表示弧上的权值。若弧不存在,则置arcs为∞(在本程序中为MAXCOST)。S为已找到的从v出发的的终点的集合,初始状态为空集。那么,从v出发到图上其余各顶点v_i可能达到的长度的初值为D=arcs[Locate Vex(G,v_i )],v_i∈V; \ 2)选择v_j,使得D[j]=Min{D|v_i∈V-S}; \ 3)修改从v出发的到集合V-S中任一顶点v_k的最短路径长度。 )
    问题描述
    ( 在有向图G=(V,E)中,假设每条边E[i]的长度为w[i],找到由顶点V_0到其余各点的最短值。 )
    算法思想
    ( 按路径长度递增次序产生算法: \ 把顶点集合V分成两组: \ (1)S:已求出的顶点的集合(初始时只含有源点V0) \ (2)V-S=T:尚未确定的顶点集合 \ 将T中顶点按递增的次序加入到S中,保证: \ (1)从源点V_0到S中其他各顶点的长度都不大于从V_0到T中任何顶点的最短路径长度 \ (2)每个顶点对应一个距离值 \ S中顶点:从V_0到此顶点的长度 \ T中顶点:从V_0到此顶点的只包括S中顶点作中间顶点的最短路径长度 \ 依据:可以证明V_0到T中顶点V_k的,或是从V_0到V_k的直接路径的权值;或是从V_0经S中顶点到V_k的路径权值之和。 \ (反证法可证) \ 求最短路径步骤 \ 算法步骤如下: \ G={V,E} \ 1初始时令S={V_0},T=V-S={其余顶点},T中顶点对应的距离值 \ 若存在(V_0,V_i),d(V_0,V_i)为(V_0,V_i)弧上的权值 \ 若不存在(V_0,V_i),d(V_0,V_i)为infty \ 2从T中选取一个与S中顶点有关联边且权值最小的顶点W,加入到S中 \ 3对其余T中顶点的距离值进行修改:若加进W作中间顶点,从V_0到V_i的距离值缩短,则修改此距离值 \ 重复上述步骤2、3,直到S中包含所有顶点,即W=V_i为止 )
    代码

    #include<iostream>
    #include<climits>
    #include<cstdlib>
    #define MAXN 10001
    using namespace std;
    int a[MAXN][MAXN]={0},b[MAXN];
    bool s[MAXN]={0};
    int main(){
    	ios::sync_with_stdio(false);
    	int n,m;
    	cout<<"点数&边数"<<endl;
    	cin>>n>>m;
    	for(int i=1;i<=m;i++){
    		int x,y,z;
    		cin>>x>>y>>z;
    		a[x][y]=z;
    		a[y][x]=z;
    	}
    	b[1]=0;
    	for(int i=2;i<=n;i++)b[i]=INT_MAX;
    	for(int i=1;i<=n;i++){
    		int minn=INT_MAX,x;
    		for(int j=1;j<=n;j++)
    			if(!s[j]&&b[j]<minn)
    			{
    				minn=b[j];
    				x=j;
    			}
    		s[x]=1;
    		for(int j=1;j<=n;j++)if(a[x][j]&&!s[j]&&b[j]>b[x]+a[x][j])b[j]=b[x]+a[x][j];
    	}
    	for(int i=1;i<n;i++)cout<<b[i]<<"->";
    	cout<<b[n]<<endl;
    	return 0;
    }
    
  • 相关阅读:
    iOS进阶_三方使用步骤
    Runtime
    感想
    git
    随笔感想
    关于APP上架问题需要ipad图标的问题
    ubuntu安装
    JNI和NDK
    数据结构——队列链表实现
    数据结构——栈的实现(数组、Java)
  • 原文地址:https://www.cnblogs.com/liusu123456/p/13736726.html
Copyright © 2011-2022 走看看