dijstra+超级源点:1488.最短距离

做前分析

本题明显的一个多源/多汇最短路问题,理应用floyd算法 ,但是N<10^{5},而floyd时间复杂度为O(n^{3}),所以floyd不能拿到全部的分。

而多源/多汇最短路问题的另一个常见做法:单源最短路+超级源点/汇点(差不多意思,一个是起点,一个是终点,用方向体现),例如本题,权值全是正的且n~m(为稀疏图),考虑dijkstra算法堆优化版,时间复杂度为m\log n约等于5千万,成立。

代码注意点

本题是稀疏图,用邻接表存储,要把表头数组h[N]全部赋-1;

dijkstra步骤:

1.初始化距离,起点赋予0,其余为无穷大(本题起点为超级源点0,而非1)

2.循环n次,找n个点到起点0的最短距离

  1. 找当前距离起点距离最短的点,认为此时该点距离起点距离最近
  2. 标记该点已经是找到最短距离的点
  3. 用该点更新取余与之相连的点距离

堆优化注意点:

  1. 用stl里优先队列可以实现堆.
  2. 优先队列中无法保证元素个数,我们把所以距离变化的点全部存入,一个点大概率会被存入多次,所以用判重数组st记录,已经找到最短距离点不在进行操作

超级源点/超级汇点:

  1. 同时有多个源点与汇点-----同时建立超级源点与超级汇点
  2. 有多个源点与一个汇点------建立超级源点,则汇点到多个源点中的最短距离为到超级源点的最短距离
  3. 有多个汇点与一个源点-------建立超级汇点
  4. 超级源点:正常i=0不会用,认为0为超级源点,add(0,源点,0);(只要设0-源点,说明该点为源点);s.push({0,0}); dis[0]=0
  5. 超级汇点:正常i=0不会用,认为0为超级汇点,add(源点,0,0);(只要设源点-0,说明该点位超级汇点)

本题的数据陷阱:本题为无向图,则idx会变为2*M,而我们又设立了超级源点,k<N,最大为N,则我们应该设N=300010才够

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=300010;
typedef pair<int,int> pll;
#define x first
#define y second
int h[N],w[N],ne[N],e[N],idx;
int dis[N],st[N];
int n,m,k,q;

void add(int a,int b,int c)
{
	e[idx]=b; w[idx]=c; ne[idx]=h[a]; h[a]=idx++;
}

void dijkstra()
{
	memset(dis,0x3f,sizeof dis);
	dis[0]=0;
	priority_queue<pll,vector<pll>,greater<pll>>s;
	s.push({0,0});
	
	while(s.size())
	{
		pll t=s.top(); s.pop();
		int distance=t.x,ver=t.y;
		
		if(st[ver])continue;
		st[ver]=1;
		
		for(int i=h[ver];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(dis[j]>distance+w[i])
			{
				dis[j]=distance+w[i];
				s.push({dis[j],j});
			}
		}
	}
}

int main()
{
	memset(h,-1,sizeof h);
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int a,b,c; scanf("%d%d%d",&a,&b,&c);
		add(a,b,c); add(b,a,c);
	}
	
	cin>>k;
	while(k--)
	{
		int a; scanf("%d",&a);
		add(0,a,0);
	}
	
	dijkstra();
	
	cin>>q;
	while(q--)
	{
		int x; scanf("%d",&x);
		cout<<dis[x]<<endl;
	}
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值