hdu1874畅通工程续——最短路(Dijkstra算法)(spfa算法)

本文详细介绍了Dijkstra算法的原理和实现方法,通过两种不同的代码实现方式帮助读者理解如何找到图中两点间的最短路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给你那个城市,再给你m个路段及长度。询问你从start到end的最小距离。

思路:Dijkstra算法的模板。

我对Dijkstra的理解:

用二维数组模拟两个城市之间的关系,然后用一个一维数组不断更新起始点到各个城市的距离。

从与起始点相关的路中选出最短的城市,然后用这个城市去遍历所有城市(已经用过的城市不会用的),凡是比一维数组中的距离近就更新一维数组,这样就能把起始点与这些城市联系起来,并且是最近的。

不要以为这样就结束了,上述一次遍历,还有许多城市没有用到,为了防止通过其他城市,到达终点的距离更近,要跑n-1次这样的循环。目的就是找最近中最近的。

代码::

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
const int inf = 1<<30;  //定义最大数 
using namespace std;
int n,m;
int map[300][300];
int mark[300],dis[300];
void Dijkstra(int s,int e)
{
int i,j,min,pos;
memset(mark,0,sizeof(mark));
mark[s]=1;//标记一下, 
for(i=0;i<n;i++)//用一位数组记录start点到所有点的距离 
{
dis[i]=map[s][i];
}
for(i=1;i<n;i++)//核心代码,不断更新所有城市,跑一次更新一次 
{
min=inf;
for(j=0;j<n;j++)//选出每次更新最近的点 
{
if(dis[j]<min&&mark[j]==0)
{
min=dis[j];
pos=j;
}
}
mark[pos]=1;//标记筛选出来的点 
for(j=0;j<n;j++)//用筛选出来的点遍历所有点的距离,方便查找或下一次选择最近的点 
{
if(dis[pos]+map[pos][j]<dis[j]&&mark[j]==0)
{
dis[j]=dis[pos]+map[pos][j];
}
}
}
}
int main()
{
int i,j,x,y,z,start,end;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=0;i<n;i++)//初始化二维数组 
{
for(j=0;j<n;j++)
{
map[i][j]=inf;
}
map[i][i]=0;
}
for(i=0;i<m;i++)//用二维数组记录城市之间的距离 
{
scanf("%d%d%d",&x,&y,&z);
if(z<map[x][y])
{
map[x][y]=map[y][x]=z;
}
}
scanf("%d%d",&start,&end);
Dijkstra(start,end);
printf("%d\n",dis[end]==inf?-1:dis[end]);
}
return 0;
}

后面这个是时下比较流行的吧,关键的地方是前向星的使用,给大家一个网址,是学习前向星的,按照说的模拟一下,就能明白差不多了

http://blog.youkuaiyun.com/war___ning/article/details/46315037

本题代码如下

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
#define inf 100000000
using namespace std;
struct node
{
int to,next,weight;
}city[100050];
int n,m;int cut;
int mark[10010];int head[10010];int dis[10010];


void add(int a,int b,int c)
{
city[cut].weight=c;
city[cut].to=b;
city[cut].next=head[a];
head[a]=cut++;
}
void spfa_bfs(int s)
{
int l,i;
queue<int>q;
mark[s]=1;
dis[s]=0;
while(!q.empty()) q.pop();
q.push(s);
while(!q.empty())
{
l=q.front();
q.pop();
mark[l]=0;
for(i=head[l];i+1;i=city[i].next)
{
if(city[i].weight+dis[l]<dis[city[i].to])
{
dis[city[i].to]=city[i].weight+dis[l];
if(mark[city[i].to]==0)
{
q.push(city[i].to);
mark[city[i].to]=1;
}
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
cut=0;
memset(head,-1,sizeof(head));
memset(city,0,sizeof(city));
for(int i=0;i<n;i++)
{
dis[i]=inf;mark[i]=0;
}
int x,y,z;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
int start,end;
scanf("%d%d",&start,&end);
spfa_bfs(start);
if(dis[end]>=inf) printf("-1\n");
else printf("%d\n",dis[end]);
}
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值