链式前向星+Dijkstra优先队列优化(应该挺有用)

在这里插入图片描述
这题就是找树上两个点之间的距离,然后这距离是奇数就输出Yes,是偶数就输出No。可以用链式前向星+队列优化的Dijkstra解决,至于队列优化的Dijkstra算法时间复杂度好像是O(nlogn+m),但是其原理我还理解的不够透彻,等以后理解透彻后再对这篇博客进行修改。
下面直接放代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector> 
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];
struct cmpx
{
	bool operator() (int &a,int &b) const
	{
		return dis[a]>dis[b];
	}
};//优先队列的排序方式 
//------------------------------------------------------------------------------------
void Dijkstra(int x)
{
	priority_queue<int,vector<int>,cmpx > q;
	memset(dis,0x3f,sizeof(dis));//刚开始x到各点的最短距离都不确定,全部初始化为inf 
	dis[x]=0;//自己到自己的最小距离是0 
	q.push(x);//确定最小距离的点扔进优先队列中 
	while(!q.empty())//队列不为空说明还有点没有确定最小距离,就要继续进行循环 
	{
		int u=q.top();//用队首的点松弛其它与其相邻的边? 
		q.pop();//出列代表我准备用它松弛了其它与其相邻的边? 
		for(int k=head[u];k!=0;k=dat[k].next)//遍历与队首相连的边 
		{
			int v=dat[k].to;
			if(dis[v]>dis[u]+dat[k].w)
			{
				dis[v]=dis[u]+dat[k].w;//能松弛就更新 
				q.push(v);//然后把被松弛的边的终点扔进优先队列中 
			}
		}
	}
}
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;
	Dijkstra(a);
	if(dis[b]%2==1) cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值