2014年04月16日

                    DIJKSTRA算法实现单源最短路
本人很懒并且很渣,所以写得不合适的地方还请各位大牛指出, 2014年04月16日 - 深海灬孤独 - 深海灬孤独的博客
注:下面针对的图是无向图,并且采用邻接矩阵的方式存储图
   先来说明下什么是最短路,从一个给定的顶点开始,到任意一个顶点的最短路径,就成为源点到该点的最短路径
 算法原理:

 按路径长度递增次序产生最短路径算法:

  把V分成两组:

  (1)S:已求出最短路径的顶点的集合

  (2)V-S=T:尚未确定最短路径的顶点集合

  将T中顶点按最短路径递增的次序加入到S中.

  保证:

    (1)从源点V0到S中各顶点的最短路径长度都不大于从V0到T中任何顶点的最短路径长度

  (2)每个顶点对应一个距离值

  S中顶点:从V0到此顶点的最短路径长度

  T中顶点:从V0到此顶点的只包括S中顶点作中间顶点的最短路径长度

  依据:可以证明V0到T中顶点Vk的最短路径,或是从V0到Vk的直接路径的权值;或是从V0经S中顶点到Vk的路径权值之和 。

好的,这不是我的风格,本段话摘自勇者王的博客。。。

   接下来是我自己的理解:其实这个算法就是把图中所有的顶点分成两个几个s,v,起先s集合只有给定的源点,然后去寻找当前的最短路,把另个属于v集合的顶点加入到s集合,重复上述操作,知道s里包含所有的顶点、

   来看一个例子  ,下图是一个普通的带权值的有向图,我们把顶点1作为源点,接下来去寻找最短路,先给出我的一张手绘稿2014年04月16日 - 深海灬孤独 - 深海灬孤独的博客

       2014年04月16日 - 深海灬孤独 - 深海灬孤独的博客2014年04月16日 - 深海灬孤独 - 深海灬孤独的博客

   2014年04月16日 - 深海灬孤独 - 深海灬孤独的博客
  先把上面的三张图理解了
下面是代码实现
  先说下使用的一些数据结构
int G[][],  矩阵,存放权值
int prev[],这个一维数组用来存放最短路上一个顶点的前一个顶点
int dist[],这个一维数组存放从源点出发到任意点的最短路
bool used[],标记数组,其实就是来判断顶点是否加入到集合s中
好的,有了这些基础,差不多可以码代码了,不过我们得定义一些宏
#define maxn 105 //最大顶点个数
#define mx 10000000   //表示两个点之间没有路径
PS:这个代码是我AC的一道杭电acm上的题的源码,比较水的,我加了下注释 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1874

#include<stdio.h>

#define maxn 105

#define mx 10000000

int G[maxn][maxn];

int prev[maxn],dist[maxn];

void Dijkstra(int n,int Source_v)

{

     bool used[maxn]; //作用上面已经介绍过

     int i ,j,k;

     for(i=1;i<=n;i++)

    {

       used[i]=0; //初始化

       dist[i]=G[Source_v][i];//那么一开始的最短路当然是直接由源顶点到目标顶点的权值的大小

if(dist[i]==mx)//如果说没有直接路径

prev[i]=0; //我们认为这个顶点的依附顶点(前一个顶点)为0

else

   prev[i]=Source_v;//与源顶点直接相连 ,前一个顶点就是源顶点


used[Source_v]=1; //表示源顶点已经标记,已加入到集合s中

dist[Source_v]=0;//源顶点到源顶点距离为0 

for(i=2;i<=n;i++)//寻找最短路 ,注意i是从2开始循环的,第一个顶点是源顶点

{

int u=Source_v;//存放一个存在当前最小权值边的顶点 

int min=mx;

for(j=1;j<=n;j++) //此循环的目的是寻找到当前最小权值边

if(!used[j] && min>dist[j]) //满足条件:既没有加入到集合s中,也比当前最小值要更小

{

min=dist[j]; //更新

u=j;

}

used[u]=1;//显然要把这个顶点加进来,标记1

for(j=1;j<=n;j++) //更新

{

if(!used[j] && G[u][j] < mx)//加入从u到j有路径

{

int newdist=G[u][j]+dist[u];//松弛操作

if(newdist<dist[j])//判断Soure_v到j的路径和Source_v到u再到j的路径大小

{

dist[j]=newdist;

prev[j]=u;

}

}

}

}

int main()

{

int n,m;

while(~scanf("%d%d",&n,&m))

{

int i,j,a,b,c,s,t;

for(i=0;i<=n;i++)

 for(j=0;j<=n;j++)

   {

                        G[i][j]=mx;

                       G[j][i]=mx;//这样表示无向图

    }

for(i=1;i<=m;i++)

{

scanf("%d%d%d",&a,&b,&c);

if(c<G[a+1][b+1]) //防止重边

{

G[a+1][b+1]=c;

    G[b+1][a+1]=c;

}

}

scanf("%d%d",&s,&t);

s+=1;

t+=1;

Dijkstra(n,s);

if(dist[t]!=mx)

 printf("%d\n",dist[t]);

                else

                    printf("-1\n");

}

return 0;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值