图 求单源最短路径 dijsktra思想

思想:

(1)初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,U中顶点u距离为边上的权(若v与u有边<v,u>)或∞(若u不是v的出边邻接点)。
(2)从U中选取一个距离v最小的顶点k,把k加入S中(该选定的距离就是v到k的最短路径长度)。
(3)以k为新考虑的中间点,修改T中各顶点的距离:若从源点v到顶点u(u∈T)的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边<k,u>上的权。
(4) 重复步骤(2)和(3)直到所有顶点都包含在S中。

矩阵

#include<cstdio>
#include<cstring>
using namespace std;
int i,j,k,n,m,x,y,h,minn,s;
int d[105][105],c[105];
bool f[105];
int main()
{
               scanf("%d%d%d",&n,&m,&s);   
                   //s为单源结点,即起始结点 
    for(i=0;i<n;++i)
       for(j=0;j<n;++j)
          d[i][j]=2000000000; 
    memset(f,false,sizeof(f));      
          //标志结点是否被访问过,flase表未访问,即集合u,true表示集合s 
    for(i=1;i<=m;++i)
    {
        scanf("%d%d%d",&x,&y,&h);
        d[x][y]=h;
    }
    f[s]=true;         
               //将单源结点s标记为true,即放入集合s 
    for(j=0;j<n;++j)        c[j]=d[s][j]; 
              //存放单源结点到其余结点的最短距离 
    c[s]=0;         
for(i=1;i<n;++i)   //n+1个结点共进行n轮即可 
{
      minn=2000000000;k=-1;
      for(j=0;j<n;++j)

       if((f[j]==false)&&(c[j]<minn))   //在没有被访问过的点中找一个结点k使单源结点0离它的距离最小 
       {
     minn=c[j];k=j;
        }
       if(k==-1)  break;  //如果提前发现都已经找到最短路径了
       f[k]=true;    //将k点加入s中
       for(j=0;j<n;++j)
            if(c[j]>d[k][j]+c[k]) //如果经过k点可以使i点到j点的距离更短
          c[j]=d[k][j]+c[k];        
}
for(j=0;j<n;++j)
     printf("%d ",c[j]);
return 0;    
}

邻接表

#include<cstdio>
#include<cstring>
using namespace std;
struct node{
    int x,wi,next;
}a[210000];
int i,j,k,n,e,x1,y1,w1,qi;
int c[2005];
bool f[2005];
int main(){
    scanf("%d%d%d",&n,&e,&qi);
    for(i=0;i<n;++i){
        a[i].x=i;a[i].next=0;
    }
    k=n;
    for(i=1;i<=e;++i){
        scanf("%d%d%d",&x1,&y1,&w1);
        a[++k].next=a[x1].next;a[k].x=y1;a[k].wi=w1;a[x1].next=k;
    }
for(i=0;i<n;++i)  c[i]=2100000000;
    memset(f,true,sizeof(f));
    f[qi]=false;
    c[qi]=0;
    for(j=a[qi].next;j;j=a[j].next){
        k=a[j].x;
        c[k]=a[j].wi;
    }
    for(i=0;i<n;++i){
        int minn=2100000000;
        for(j=0;j<n;++j)
          if(f[j]&&minn>c[j]){
                minn=c[j];
                k=j;
          }
        f[k]=false;
        for(j=a[k].next;j;j=a[j].next){
            int k1=a[j].x;
            if(c[k1]>c[k]+a[j].wi)
               c[k1]=c[k]+a[j].wi;
        }           
    }
    for(i=0;i<n;++i)  printf("%d ",c[i]);
    return 0;    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值