信奥一本通:1382 :链式前向星创建图+优先队列+djk算法

本文详细描述了如何使用Spfa算法在大规模无向图中寻找从1到N的最短路径,涉及数据结构如链式前向星和优先队列的运用。
摘要由CSDN通过智能技术生成

1382:最短路(Spfa)


时间限制: 1000 ms         内存限制: 65536 KB
提交数:15578    通过数: 4682

【题目描述】

给定 M� 条边, N� 个点的带权无向图。求 11到 N� 的最短路。

【输入】

第一行:N,M(N<=100000,M<=500000)�,�(�<=100000,�<=500000);

接下来M�行33个正整数:ai,bi,ci表示ai,bi之间有一条长度为ci的路,ci<=1000��,��,��表示��,��之间有一条长度为��的路,��<=1000。

【输出】

一个整数,表示 11 到 N� 的最短距离。

【输入样例】

4 4
1 2 1
2 3 1
3 4 1
2 4 1

【输出样例】

2

【提示】

【样例解释】

注意图中可能有重边和自环,数据保证 11 到 N� 有路径相连。

//1382:最短路(Spfa) ;链式前向星 创建图,优先队列找最小的dis结点u,通过u更新u的邻边v结点到起始结点的距离dis【v】,注意:e的规模边的2倍空间

#include<bits/stdc++.h>

using namespace std;

// 链式前向星 创建图,效率最高,只需要按照边的条数创建

struct edge   ///u-v 有一条边

{

       int to; // 边的终止结点

       int w; // u-v距离为w

       int next; // u的下一个边的序号

}e[1000005];// 边的条数

int head[100000];//记录这个结点 的起始邻边 边的的序号  

int cnt=0;// 边从0开始

void addedge(int x,int y,int z)

{

       cnt++; // 第一条邻边的序号

       e[cnt].to=y; // 终止结点为y

       e[cnt].w=z; // 距离为在

       e[cnt].next=head[x]; // 下一条li

       head[x]=cnt;// x的临边记录下一条边的序号    

}

int n,m; // n 是顶点数,m是边数

typedef struct node

{

       long long d; // 距离

       int num; // 序号

       bool operator<(const node &nd1)const{

              return nd1.d<d; // 从大到小

       }

}node;

long long dis[100005];// 每个点到起始结点的距离

int visit[100005];// 标记结点是否已经访问

const int  inf=0x3f3f3f3f;

void djk()

{

       memset(dis,inf,sizeof(dis)); // 默认距离无穷大

       dis[1]=0; // 起始到自己的距离为0

       priority_queue<node> qu; // dis 从小到大

       node nd;

       nd.d=0;

       nd.num=1;

       qu.push(nd); // 起始结点进队列

       while(!qu.empty()) // 

       {

              node nf=qu.top();// 优先队列操作入栈所

              qu.pop(); //删掉

              int u=nf.num;// 找到了没有访问的,最小的dis的序号

//           if(visit[u]==1)

//           continue;   

              visit[u]=1;  // 标记已经访问

              // 通过u (起始u点,可能更新到u的邻边结点v的距离)

              for(int j=head[u];j>0;j=e[j].next) // j 是u邻边的边序号

              {

                     int v=e[j].to;// v是u的邻边结点

                     if(visit[v]==0&&dis[v]>dis[u]+e[j].w) // 到v的距离,通过uv这条边更新

                  {

                            dis[v]=dis[u]+e[j].w;// 更新距离

                            qu.push(node{dis[v],v}); // v 结点进队列

                     }

              }

       }

}

int main()

{

       cin>>n>>m;

       int i,j;

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

       {

              int x,y,z;

              scanf("%d%d%d",&x,&y,&z);//cin>>x>>y>>z;

              if(x==y)

              continue;

              addedge(x,y,z);

              addedge(y,x,z);

       }

    djk();

   printf("%lld",dis[n]);

}

  • 19
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值