标签:
总感觉Dijkstra跟prim思路很像,现在仔细想想虽然都算的上贪心,但是Dijkstra比prim复杂一点
prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的点集合A,另一个集合为未加入生成树的点B,它的具体实现过程是:
第1步:所有的点都在集合B中,A集合为空。
第2步:任意以一个点为开始,把这个初始点加入集合A中,从集合B中减去这个点(代码实现很简单,也就是设置一个标示数组,为false表示这个点在B中,为true表示这个点在A中),寻找与它相邻的点中路径最短的点,如后把这个点也加入集合A中,从集合B中减去这个点(代码实现同上)。
第3步:集合A中已经有了多个点,这时两个集合A和B,只要找到A集合中的点到B集合中的点的最短边,可以是A集合中的与B集合中的点的任意组合,把这条最短边有两个顶点,把在集合B中的顶点加入到集合A中,(代码实现的时候有点技巧,不需要枚举所有情况,也就是更新操作)。
第4步:重复上述过程。一直到所有的点都在A集合中结束。
Dijkstra比prim算法的过程稍微多一点点步骤,但是思想确实巧妙的,也是贪心原理,它的目的是求某个源点到目的点的最短距离,总的来说,dijkstra算法也就是求某个源点到目的点的最短路,求解的过程也就是求源点到整个图的最短距离,次短距离,第三短距离等等(这些距离都是源点到某个点的最短距离)。。。。。求出来的每个距离都对应着一个点,也就是到这个点的最短距离,求的也就是原点到所有点的最短距离,并且存在了一个二维数组中,最后给出目的点就能直接通过查表获得最短距离。
第1步:以源点(假设是s1)为开始点,求最短距离,如何求呢? 与这个源点相邻的点与源点的距离全部放在一个数组dist[]中,如果不可达,dist[]中为最大值,这里说一下,为什么要是一维数组,原因是默认的是从源点到这个一维数组下标的值,只需要目的点作为下标就可以,这时从源点到其他点的最短的“一”条路径有了,只要选出dist[]中最小的就行(得到最短路径的另一个端点假设是s2)。
第2步:这时要寻找源点(假设是s1)到另外点的次短距离,这个距离或者是dist[]里面的值,或者是从第1步中选择的那个最短距离 + 从找到点(假设是s2)出发到其他点的距离(其实这里也是一个更新操作,更新的是dist[]里面的值),如果最短距离 + 从这点(假设是s2)到其他点的距离,小于dist[]里面的值,就可以更新dist[]数组了,然后再从dist[]数组中选一个值最小的,也就是第“二”短路径(次短路径)。
第3步:寻找第“三”短路径,这时同上,第二短路径的端点(s3)更新与之相邻其他的点的dist[]数组里面的值。
第4步:重复上述过程n - 1次(n指的是节点个数),得出结果,其实把源点到所有点的最短路径求出来了,都填在了dist[]表中,要找源点到哪个点的最短路,就只需要查表了。
附一道题:
hdu1874
#include<iostream>
using namespace std;
const int maxnum=1005;
const int maxint=99999;
int dist[maxnum];//起点到终点的距离
int c[maxnum][maxnum];//用于储存两点之间的距离
void Dijkstra(int S,int N,int * dist,int c[maxnum][maxnum])
{
bool s[maxnum];//判断是否已加入集合S中
//初始化起始点到其他点的距离
for(int i=0;i<N;i++)
{
dist[i]=c[S][i];
s[i]=0;
}
//起始点被标记,最短距离为0
s[S]=1;
dist[S]=0;
//遍历剩下n-1个点
for(int i=1;i<N;i++)
{
int u=S;
int temp=maxint;
//找出尚未标记的点中,与起始点距离最短的
for(int j=0;j<N;j++)
if(!s[j]&&dist[j]<temp)
{
u=j;
temp=dist[j];
}
s[u]=1;
//最难理解的地方:找到当前已于起始点联通的点的最短距离,随着每一次遍历,会更新,最终达到最短
for(int k=0;k<N;k++)
if(!s[k]&&dist[k]>dist[u]+c[u][k])
{
dist[k]=dist[u]+c[u][k];
}
}
}
int main ()
{
int N,M;
while(cin>>N>>M)
{
int A,B,X;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
c[i][j]=maxint;
for(int i=1; i<=N; ++i)
dist[i] = maxint;
for(int i=0;i<M;i++)
{
cin>>A>>B>>X;
if(X<c[A][B])
{
c[A][B]=X;
c[B][A]=X;
}
}
int S,E;
cin>>S>>E;
Dijkstra(S,N,dist,c);
if(dist[E]==maxint)
cout<<"-1"<<endl;
else
cout<<dist[E]<<endl;
}
return 0;
}
标签:
原文地址:http://www.cnblogs.com/ACWQYYY/p/4375428.html