hdu1874 畅通工程续 dijkstra 最短路
http://acm.hdu.edu.cn/showproblem.php?pid=1874
1.dijkstra算法简介
Dijkstra算法是由E.W.Dijkstra于1959年提出,又叫迪杰斯特拉算法,它应用了贪心算法模式,是目前公认的最好的求解最短路径的方法。算法解决的是有向图中单个源点到其他顶点的最短路径问题,其主要特点是每次迭代时选择的下一个顶点是标记点之外距离源点最近的顶点。但由于dijkstra算法主要计算从源点到其他所有点的最短路径,所以算法的效率较低。
2.dijkstra算法基本过程
假设路网中每一个节点都有标号 是从出发点s到点t的最短路径长度;表示从s到t的最短路径中t点的前一个点。求解从出发点s到点t的最短路径算法的基本过程为:
1. 初始化。出发点设置为:
标记起源点s,记k = s,其他所有点设为未标记。
2. 检验从所有已标记的点k到其他直接连接的未标记的点j的距离,并设置:
3. 选取下一个点。从所有未标记的点中选取 最小的点i,点i被选为最短路径中的一点,并设为已标记的。
4. 找到点i的前一点。从已经标记的点集合中找到直接连接到点i的点,并标记为 。
5. 标记点i。如果所有的点已标记,则算法结束。否则,记k = i,转到2继续。
从以上算法的步骤中可以看出 :dijkstra算法的关键部分是从未标记的点中不断地找出距离源点距离最近的点,并把改点加入到标记的点集合中,同时更新未标记的点集合中其余点到起始点的最短估计距离[z1] 。
以一个带有权值的无向图为例,用dijkstra算法分析从源点A到目标点F的最短路径。
1. 用带有权值的一个矩阵w表示含有n各节点的带权无向图, 代表弧段 的权值,如果从节点 到节点 不连通,那么 ,带权值图邻接矩阵如下图所示.设置A为源点,G为目的点, 代表从节点A到有向图中其他节点 的最短路径长度。设置初始值 代表标记的节点集合。
2. 是从A点出发求出的一条最短路径上的终止节点,令 ;
3. 修改起始节点A到集合之间的最短路径的长度值,如果d(j)+w(j,k) < d(k),那么d(k) = d(j) + w(j,k);
4. 重复步骤2、3的操作N-1次,最终得到从起始节点A到其他节点的最短路径,按照递增的顺序排列路径的长度。
3.dijkstra算法的流程图如下所示:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 # define INF 99999999 5 6 using namespace std; 7 int n,m,u,v,w,s,e; 8 int visit[300],map[200][200]; 9 10 int dijkstra(); 11 int main() 12 { 13 while(scanf("%d%d",&n,&m)!=EOF) 14 { 15 for(int i=0; i<n; i++) 16 { 17 visit[i]=0; 18 for(int j=0; j<n; j++) 19 if(i==j)map[i][j]=0; 20 else map[i][j]=INF; 21 } 22 while(m--) 23 { 24 cin>>u>>v>>w; 25 if(w<map[u][v])map[u][v]=map[v][u]=w; 26 } 27 cin>>s>>e; 28 dijkstra(); 29 } 30 return 0; 31 } 32 int dijkstra() 33 { 34 int temp, min; 35 visit[s]=1; 36 for(int i=0; i<n; i++) 37 { 38 min=INF; 39 for(int j=0; j<n; j++) 40 { 41 if(min>map[s][j]&&visit[j]==0) 42 { 43 min=map[s][j]; 44 temp=j; 45 } 46 } 47 visit[temp]=1; 48 for(int j=0; j<n; j++) 49 if(visit[j]==0&&map[s][temp]+map[temp][j]<map[s][j])//map[temp][s]可以替换成min 50 map[s][j]=map[j][s]=map[s][temp]+map[temp][j];//map[temp][s]可以替换成min 51 52 } 53 if(map[s][e]==INF)printf("-1\n"); 54 else printf("%d\n",map[s][e]); 55 return 0; 56 }