单源最短路径 洛谷-P4779

题目链接
dijkstra 算法讲解

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue> 
#define MaxN 100010
#define MaxM 500010 
using namespace std;

struct Edge{
	int to;//终点 
	int len;//权值 
	int next;//下条边的存储位置 
};

struct Edge tu[MaxM];

struct Node{
	int x;
	int len;
	//重载运算符 
	bool operator < (const Node &x) const
	{
		return x.len < len ;
	}
};
priority_queue <Node> q;//优先队列 

//链式前向星储存图 
int head[MaxN],id;

int dis[MaxN];//记录最短距离

bool flag[MaxN];

int n,m,s;//n个点,m条有向边,源点s 

//链式前向星储存图模板函数 
void Add(int u,int v,int w)
{
	id++;
	tu[id].to=v;
	tu[id].len=w;
	tu[id].next=head[u];
	head[u]=id;
	return ;
}
/*图存储的理解:
我们假设Add函数现在执行第一次:
id=1,head[u]=1表示以u为起点的边最后是在第一条 
现在Add函数执行第二次(两次都是同一个起点):
id=2,tu[id].next=1表示下次要去第一条边查询以u为起点的边,head[u]=2表示以u为起点最后是在第两条; 
现在Add函数执行第三次(不同的起点)
id=3,tu[id].next=head[u]=0(新起点head[u]为0),head[u]=3以u为起点最后是在第三条
现在来看for(int i=head[x]; i; i=tu[i].next)
根据head[x]的定义我们知道i现在是x为起点的最后一条边的存储位置
所以直接用tu[i]便可访问对应的信息
i=tu[i].next,访问与x同起点的下一条边,为0循环结束 
 */ 
void Dij()
{
	dis[s]=0;
	Node res;
	res.x=s,res.len=0;
	q.push( res );
	while( !q.empty() )
	{
		Node temp=q.top();
		q.pop();
		int x=temp.x;
		
		if( flag[x] )//flag[x]判断当前是否是已经确定最短路径的点 
			continue;
			
		flag[x]=true;//确定最短路径的点 
		 
		for(int i=head[x]; i; i=tu[i].next)//遍历与x相关的点 
		{
			//head[x]表示这是与x相关的第几条边,tu[i].next是下一条边的存储位置 
			int y=tu[i].to;
			if( dis[y] > dis[x] + tu[i].len )
			{
				dis[y]=dis[x]+tu[i].len;//更新最短路 
				if( !flag[y] )
				{
					res.x=y,res.len=dis[y];
					q.push(res);
				}
			}
		}
	}
	return ;
} 


int main()
{
	int INF=0x7fffffff;
	
	scanf("%d%d%d",&n,&m,&s);
	
	for(int i=1; i<=n; i++)
		dis[i]=INF;
		
	int u,v,w;
	for(int i=0; i<m; i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		Add(u,v,w);//存储图 
	}
	
	Dij();
	
	for(int i=1; i<=n; i++)
		printf("%d ",dis[i]);
	return 0;
}
 
发布了14 篇原创文章 · 获赞 0 · 访问量 214
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 游动-白 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览