最短路板子

spfa

#include <bits/stdc++.h>
using namespace std; 
int dis[500010], n, m, x, y, w, t = 1, s, h, head[500010], tot;
bool v[100010];
queue<int> q;//手写队列:int q[200000];
/*
head[i]表示到达i点的最后一条边的编号; 
dis[i]表示从起点到i点目前为止的最短距离; 
vis[i] = 1;表示点i在队列里; 
vis[i] = 0;表示点i不在队列里; 
数组q是手写队列; 
h是队头,t是队尾。 
*/
struct node
{
    int to;//这条边的终点; 
    int len;//这条边的长度; 
    int from;//前一条边; 
}e[500010]; 
void add(int from/*起点*/,int to/*终点*/,int w/*权值*/)
{
    e[++ tot].to = to;//更新当前这条边的终点; 
    e[tot].len = w;//更新当前这条边的长度; 
    e[tot].from = head[from];//e[tot].from表示当前读入的这条边的上一条边;head[from]表示到当前读入的边为止(不包括这条边)的上一条边的序号;
    head[from] = tot;//更新为 当前读入的边为止(包括这条边)的上一条边的序号;
} 
void SPFA()
{
    while(! q.empty())
    {//队列不为空。手写队列:while(h <= t) 
    	int u = q.front();//取出队首。手写队列:h ++;  int u = q[h];
    	q.pop();//队首出队。
        v[u] = 0;
        for(int i = head[u]; i; i = e[i].from)
        {//head[u]是指可以到达点u的上一条边,如果存在head[u](也就是head[u]不为0,因为0是初始值),说明有一条边可以到达点u。所以i变成head[u]。e[i].from是指可以到达head[u]这条边的起点的边的编号。
            int h = e[i].to;
            if(dis[h] > dis[u] + e[i].len)
            {//如果从起点到v的距离大于从起点到点i,再从点i到点u,再从点u到点v的距离,更新从起点到点v的最短路;
                dis[h] = dis[u] + e[i].len;
                if(v[h] == 0)
                {//没有入过队就入队;
                    v[h] = 1;//标志改为1,表示已经入队; 
					q.push(h);//手写队列:t++;   q[t]=h;
                }
            }
        }
    } 
}  
int main(){
    cin >> n >> m >> s;
    for(int i = 1; i <= m; i ++)
    {
        cin >> x >> y >> w;//输入这条边的起点f,终点g和长度w;  
        add(x, y, w);//建图;
    } 
    for(int i = 1; i <= n; i ++)
    {
    	dis[i] = 2147483647;
	}
    dis[s] = 0;
    q.push(s);//起点入队。手写队列:q[t] = s;
    v[s] = 1;//表示起点已入队; 
    SPFA();
    for(int i = 1; i <= n; i ++)
    {
    	cout << dis[i] << ' '; 
    }
    return 0; 
}

Dijkstra

*全译文版Dijkstra堆优化。*/
#include <bits/stdc++.h>
using namespace std;
#define itn int
#define fro for
const int _ = 100086;
const int __ = 2147483647; 
int n, m, v[_], head[_], dis[_], x, y, w, t, s;
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;//小根堆。
struct hhh
{//高兴。
	int len, to, nxt;
}e[500050];
void add(int a, int b, int c)
{//链式前向星(从a走到b距离是c)
	e[++ t].len = c;//表示这条边的长度;“t”表示这是第几条边(编号)。
	e[t].to = b;//表示这条边的终点。
	e[t].nxt = head[a];//表示当前的边的上一条边;head[a]表示当前的边的上一条边的上一条边的编号;
	head[a] = t;//t”是当前的边的上一条边的编号。
}
void dijkstra(int x)
{//Dijkstra堆优化。
	q.push(make_pair(0, x));//源点的距离和它自己入堆。
	for(int i = 1; i <= n; i ++)
    {
		dis[i] = __;//初始化。
	}
	dis[x] = 0;//自己到自己的距离是0。
	while(! q.empty())
    {//堆不为空,就说明不是所有与源点联通的点都被遍历到了,就要一直找。 
		int now = q.top().second;//取出堆顶的点。
		q.pop();//把堆顶扔进垃圾桶里。
		if(v[now])
        {//被用过就跳楼。
			continue;
		}
		v[now] = 1;//标记。
		for(int i = head[now]; i; i = e[i].nxt)
        {//遍历所有与now这个点直接相邻的点。
			if(dis[e[i].to] > dis[now] + e[i].len)
            {
				dis[e[i].to] = dis[now] + e[i].len;//更新到该点的最短路。
				q.push(make_pair(dis[e[i].to], e[i].to));//将新鲜更新完的点扔进堆里。
			}
		}
	}
}
int main()
{
	cin >> n >> m >> s;
	for(int i = 1; i <= m; i ++)
    {
		cin >> x >> y >> w;
		add(x, y, w);
	}
	dijkstra(s);
	for(int i = 1; i <= n; i ++)
    {
		cout << dis[i] << ' ';
	}
	return 0;
}

感谢肝·神祇变量·OIer·硬化·悲伤蛙一世

de全译注释

posted @ 2025-05-11 22:51  BIxuan—玉寻  阅读(17)  评论(0)    收藏  举报