链式前向星+无优化Dijkstra(虽然可能没啥卵用= =)

直接放代码:

#include<iostream>
#include<cstring>
using namespace std;
//-----------------------------链式前向星的准备工作-----------------------------------
struct edge{
	int next;//上个以这条边为起点的边在存放边的数组中的位置(方便遍历) 
	int to;//终点 
	int w;//边权 
}dat[200005];//存放边的结构体(无向边大小要开2倍)
int cnt=1;//这是遍历存放边的数组用的,同时也记录着边的数量 
int head[200005];//head[u]表示以u为起点的第一条边(这里第一条指的是链式结构的头)在存放边的数组中的位置 ,无向边大小要开二倍 
void add(int u,int v,int w)//加边函数 
{
	dat[cnt].w=w;//存放边权 
	dat[cnt].to=v;//存放终点 
	dat[cnt].next=head[u];//当前边指向上一条同起点的边 
	head[u]=cnt++;//改变头结点为当前边(方便以后遍历) 
}
//------------------------------------------------------------------------------------
//-------------------------------Dijkstra的准备工作-----------------------------------
const int inf = 0x3f3f3f3f;
int dis[100005];
bool vis[100005];
//------------------------------------------------------------------------------------
int main()
{
	int n,a,b;
	cin>>n;
	for(int i=1;i<n;++i)
	{
		cin>>a>>b;
		add(a,b,1);
		add(b,a,1);//无向边 
	}
	cin>>a>>b;
	int mi=head[a];
	memset(dis,0x3f,sizeof(dis));//没初始化到的点就是a没有边到它,那么距离就是无穷大 
	while(mi!=0)//mi=0就说明当前起点的边已经遍历完了 
	{
		dis[dat[mi].to]=dat[mi].w;//初始化dis为a到各点的距离 
		mi=dat[mi].next;//遍历到下一个结点 
	}
	vis[a]=1;//a到a的距离已经确定了 
	for(int i=1;i<n;++i)
	{
		int min=inf,u;
		for(int j=1;j<=n;++j)
		{
			if(!vis[j]&&dis[j]<min)
			{
				min=dis[j];
				u=j;
			}
		}//找出此时还没确定的点到1的最小值 
		vis[u]=1;//先标记该点的最小值已经确定,下面进行操作
		mi=head[u];//找到u点能到达的点
		while(mi!=0)
		{
			if(dis[dat[mi].to]>dis[u]+dat[mi].w)
				dis[dat[mi].to]=dis[u]+dat[mi].w;//更新u点能到达的点的最小值 
			mi=dat[mi].next;//遍历到下一个结点 
		}
	}
	if(dis[b]%2==1) cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	return 0;
}

2021/5/21
核心实现部分在有重复边等特殊情况时好像出现了错误,题目如下:
在这里插入图片描述
下面是更改后的代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef long long ll;
struct edge{
	int next;
	int to;
	int w;
}dat[500005];
int cnt=1;
int head[500005];
void add(int u,int v,int w)
{
	dat[cnt].w=w;
	dat[cnt].to=v;
	dat[cnt].next=head[u];
	head[u]=cnt++;
}
const int inf=0x3f3f3f3f;
int dis[10005];
bool vis[10005];
int main()
{
	int n,m,s,a,b,c;
	cin>>n>>m>>s;
	for(int i=1;i<=m;++i)
	{
		cin>>a>>b>>c;
		add(a,b,c);
	}
	int mi=head[s];
	memset(dis,0x3f,sizeof(dis));
	while(mi!=0)
	{
		dis[dat[mi].to]=dat[mi].w;
		mi=dat[mi].next;
	}
	//vis[s]=1;
	mi=s;
	dis[s]=0;
	while(!vis[mi])//搜完整张图 
	{
		vis[mi]=1;
		for(int i=head[mi];i;i=dat[i].next)
		{
			if(!vis[dat[i].to]&&dis[dat[i].to]>dis[mi]+dat[i].w)
				dis[dat[i].to]=dis[mi]+dat[i].w;
		}
		int minn=inf;
		for(int j=1;j<=n;++j)
		{
			if(!vis[j]&&minn>dis[j])
			{
				minn=dis[j];
				mi=j;
			}
		}
	}
	for(int i=1;i<=n;++i)
	{
		if(dis[i]==inf) cout<<(ll(1)<<ll(31))-1<<" ";
		else cout<<dis[i]<<" ";
	}
	return 0;
}

相比于之前的代码,只是对核心实现的部分进行了修改,我严重怀疑以前代码错误出现在在特殊情况下没有遍历完整个图。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用Dijkstra算法求解最短路径时,可以使用链式前向星(Linked List Representation)来表示图的数据结构,以提高算法的效率。 链式前向星是一种用于存储稀疏图的数据结构,它将每个节点的邻接边以链表的形式存储。具体实现步骤如下: 1. 创建一个结构体或类来表示图的边,包括目标节点和边的权重等信息。 2. 创建一个数组,数组的每个元素表示一个节点,每个节点包含一个指向邻接边链表的指针。 3. 遍历图的所有边,对于每条边(u, v)和权重w,创建一个新的边节点,并将其插入到节点u的邻接边链表中。 4. 在Dijkstra算法中,需要使用一个优先队列(最小堆)来选择最短路径的节点。队列中的元素包括节点索引和到达该节点的距离。 5. 初始化距离数组和标记数组,距离数组记录起始节点到各个节点的最短距离,标记数组用于标记已经找到最短路径的节点。 6. 将起始节点加入优先队列,并将距离数组中起始节点的距离设为0。 7. 重复以下步骤,直到优先队列为空: a. 从优先队列中取出距离最小的节点u。 b. 遍历节点u的邻接边链表,对于每个邻接节点v,如果通过u到达v的距离更短,则更新距离数组中节点v的距离,并将节点v加入优先队列。 8. 当所有节点都被标记后,最短路径的结果就可以通过距离数组得到。 使用链式前向星可以减少遍历边的次数,提高Dijkstra算法的效率。同时,链式前向星还可以支持动态图的操作,如添加和删除边。但是,它需要额外的空间来存储链表和边节点,因此适用于稀疏图而非稠密图。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值