链式前向星+无优化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
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值