直接放代码:
#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;
}
相比于之前的代码,只是对核心实现的部分进行了修改,我严重怀疑以前代码错误出现在在特殊情况下没有遍历完整个图。