1、单源最短路径,xie_dream,给定带权有向图G=(V,E)和源点u,求从点u到其他各顶点的最短距离 Dijkstra算法 基本思想是:设置一个集合存放已经找到最短路径的顶点,的初始状态只包含源点u,设置另一个集合,-,存储原图中不在集中的点,即的补集。假设从源点u到vi的有向边为最短路径,以后每求得一条最短路径v,vk就将vk加入集合中,并将路径v,vk,vi与原来的假设相比较,取路径长度较小者为最短路径。重复上述过程,直到集合中全部顶点加入到集合中,S,T,u,vi,S,T,u,vi,vk,S,T,u,vi,vk,u,v2,v3,v4,v1,3,3,5,1,2,9,9,2,S集合,红线右
2、侧全为集合,1)先假设v1,v2,v3,v4与u相连的边就是最短路径distv1=3,distv2=2;dist3=9;dist4=10,v2,v3,v4,v1,3,3,10,1,2,9,9,2,S集合,u,u,2)找一个离u最近的点加入S集合(这里是不是有点象前一讲中的MST的Prim算法),即为v2,v2,v3,v4,v1,3,3,10,1,2,9,9,2,S集合,u,2)找一个离u最近的点加入S集合(这里是不是有点象前一讲中的MST的Prim算法),即为v2,v2,v3,v4,v1,3,3,10,1,2,9,9,2,S集合,u,再用v2去检查从v2可到达的点的原先的所有假设发现distv
3、4distv2+gv2v4,更新distv4,v2,v3,v4,v1,3,3,10,1,2,9,9,2,S集合,u,3)按上一步同样的方法找到v1加入到S集合中,v2,v3,v4,v1,3,3,10,1,2,9,9,2,S集合,u,3)按上一步同样的方法找到v1加入到S集合中,v2,v3,v4,v1,3,3,10,1,2,9,9,2,S集合,u,)按上一步同样的方法找到v4加入到S集合中,这时distv3=9distv4=10,为什么还要选呢?因为在选后,最初的假设已经被更新为distv4=4了!,v2,v3,v4,v1,3,3,10,1,2,9,9,2,S集合,u,)加入集合中,同样发现di
4、stv3distv4+gv4v3,更新!,v2,v3,v4,v1,3,3,10,1,2,9,9,2,S集合,u,算法实现过程,1,初始化dist和color 2,while(s集合中的元素个数小于n) 在dist中求最小值,并同样记录下标k 用distk去修改k一步直接可达的点的dist 将顶点k放入集合中,染为紫色,详细代码,/*Author: PrimeMusic_Fan Created on 2010年4月29日, 下午1:46*/ #include #include #define arr 110 #define blue 0 #define purple 1 #define max_
5、int 214748364 int n;/ the number of vertexs int m;/ the number of edges int garrarr;/ gij indicates the distance between i and j int patharr;/ pathi record the shorest path from source u to i int distarr;/disti indicates the shortest distance from u to i int st;/ the source vertex int colorarr;/colo
6、r the vertex void Dijkstra(int st)for(int i=1;i=n;+i)colori=blue;disti=gsti;/先假设源点u到其他点的直接相连边的长度就为最短距离pathi=st;/假设都是从u直接通过一条有向边到达,distst=0;colorst=purple; int numS=1;/S集合中元素的个数,已经加入了源点,所以为while(numS+disti)minDis=disti;k=i;/printf(“k=%dn“,k);if(k=-1)/说明找不到与源点相连的点,算法结束break;colork=purple;/找到点k,加入集合中,并
7、染为紫色/下一步,用distk去检查原先的所有不在集合,即集合中所有点的假设for(int i=1;idistk+gki)/通过点k可以使源点到i点的距离变小,更新disti=distk+gki;pathi=k; ,void DisplayPath(int v)int anarr;an0=0; while(true) an+an0=v;if(v=st)break;v=pathv;for(int i=an0;i=2;-i)printf(“%d“,ani);printf(“%dn“,an1); ,int main()while(scanf(“%d%d“, ,练习题,Pku 1847 Hdu 2066,