【模板题】【图】最短路径 经典例题 ——dijkstra+priority_queue

【经典模板】:PID341 / 星门跳跃

题目大意:从1到N有M条边,每条边距离z,求最短路

思路:dijkstra+priority_queue。本道题由于数据非常大,时间要求严,不能全部往队列里丢数据,可以在之前加个判断,本次距离是否减小,减小则往队里扔。此外由于优先队列每次都是选取最小距离,则此距离固定,则代表已访问,标记点下次访问到此点直接跳过。

注意:

1、加判断if(visit[u])和if(D[v]==-1 || D[v]>D[u]+cost);

#include<cstdio> 
#include<queue>
#include<vector>
#include<string.h>
#define MAX 300001
using namespace std;
struct node
{
    int v,c;//u->v cost=c;
    node (){}
    node(int x,int y){v=x;c=y;}
	bool operator < (const node &A) const
	{
		if (c==A.c)
			return v>A.v;
		else return c>A.c;
	}
};
vector<node>g[MAX];
bool visit[MAX];
int D[MAX];
int n,m;
void Dijkstra()
{
	priority_queue<node>Q;
	int i,u,v,cost;
	node p;
	memset(visit,0,sizeof(visit));
	memset(D,-1,sizeof(D));
	D[1]=0;
	Q.push(node(1,D[1]));
	while(!Q.empty())
	{
		p=Q.top();Q.pop();
		u=p.v;
		if (visit[u])
			continue;
		visit[u]=true;
		D[u]=p.c;
		if (u==n)
			break;
		for (i=0;i<g[u].size();i++)
		{
			v=g[u][i].v;
			cost=g[u][i].c;
			if (D[v]==-1 || D[v]>D[u]+cost);
				Q.push(node(v,D[u]+cost));
		}
	}
}

int main()
{
	int x,y,z,i;
	scanf_s("%d%d",&n,&m);
	for (i=1;i<=m;i++)
	{
		scanf_s("%d%d%d",&x,&y,&z);
		g[x].push_back(node(y,z));
		g[y].push_back(node(x,z));
	}
	Dijkstra();
	printf("%d",D[n]);
	return 0;
}

变形:726:ROADS——路径有两个属性时的处理

题目大意:从1到N有m条边,每一条边有原点s,目的d,距离l和花费t,寻找从1到n的最短路,满足花费小于k

思路:dijkstra+priority_queue。由于从队列头取出的点不一定选取成功(即虽然路程最小但是花费>k),所以不能加visit和D数组的距离判断,只能把可能的路径放入队列,让优先队列自己判断

注意:
1、优先队列是按从大到小排序的!所以排序时要注意把<变成>

2、直接入队,不需要判断!!

#include<iostream>
#include<queue>
#include<vector>
#include<string.h>
#define MAX 102
using namespace std;
int n,k;
struct node
{
	int v,L,t;
	node(){}
	node(int a,int b,int c){v=a;L=b;t=c;}
	bool operator < (const node &A)const//优先队列是按从大到小排序的!!!
	{
		if (L==A.L && t==A.t)
			return v>A.v;//要为大于号!!!
		else if (L==A.L)
			return t>A.t;
		else return L>A.L;
	}
};
vector<node> g[MAX];
int L[MAX],T[MAX];
bool flag=false;
void Dijkstra(int c)
{
	priority_queue<node> Q;
	node p;
	int u,l,t,i,v;
	memset(L,-1,sizeof(L));
	memset(T,-1,sizeof(T));
	L[c]=0;T[c]=0;
	Q.push(node(c,L[c],T[c]));
	while(!Q.empty())
	{
		p=Q.top();Q.pop();
		u=p.v;L[u]=p.L;T[u]=p.t;
		if (p.t>k)//忽略钱多的
			continue;
		if (u==n)
		{
			flag=1;return;
		}
		for (i=0;i<g[u].size();i++)
		{
			v=g[u][i].v;
			t=g[u][i].t;
			l=g[u][i].L;
			Q.push(node(v,L[u]+l,T[u]+t));
		}
	}
}
int main()
{
	int i,s,d,l,t,m;
	cin>>k>>n>>m;
	for (i=1;i<=m;i++)
	{
		cin>>s>>d>>l>>t;
		g[s].push_back(node(d,l,t));
	}
	Dijkstra(1);
	if(flag)
		cout<<L[n];
	else cout<<-1;
	return 0;
}

 

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/Always_ease/article/details/80638468
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞