对于dijkstra最短路的一些浅显的理解,希望能帮到大家

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define P pair<int,int>      //pair是一个模板类,含有两个成员数据,
const int maxn = 5e5+5;
struct tree
{
    int to, w;
};
vector<tree>a[maxn];
int dis[maxn];                 //dis代表最短的距离priority_queue
int n, m, s;
bool b[maxn];                  //判断某点是否被遍历过
priority_queue<P, vector<P>, greater<P> > Q;        //优先队列是尖括号,升序是greater<P>;最后一个有一格空格
void dijkstra()
{
    dis[s] = 0;                                        //优先队列的格式是<类型,储存容器,储存方式 >
    Q.push(P(0, s));                                    //队列的储存格式是Q.push(P(first,second));第一个是"下一个点的"最短路,第二个是"下一个点",
    b[0] = true;                                         //   "下一个点"相对于该次循环的
    while (!Q.empty())                                   //为空就返回值为真,非空返回值就为假
    {
        P p = Q.top(); Q.pop();                          //Q.top()为取出最顶端元素,因为存储方式为greater,即取出最小值,Q.pop(),是删除最顶端元素以免进入下一次循环
        int v = p.second;
        if(b[v])                                       
            continue;
        b[v] = true;
        for (int i = 0; i < a[v].size(); i++)
        {
            int u = a[v][i].to;
            if (dis[v] + a[v][i].w < dis[u])
                dis[u] = dis[v] + a[v][i].w;         //如果到下一个点u的前一个点v的距离加上到下一个点的权值的距离小于到u的距离的话就更新到u的最短距离
            if(!b[u])                                 //如果u没有被存入过,就存入u点信息,以免重复遍历u点
            Q.push(P(dis[u], u));                    //存入到u的最短路和u方便下一个循环计算
        }
    }
}


int main()
{

    scanf("%d %d %d", &n, &m, &s);
    for (int i = 0; i < m; i++)
    {
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        a[u].push_back({ v,w });
    }
    memset(dis, 0x3f, sizeof(dis));
    memset(b, 0, sizeof(b));
    dijkstra();
    for (int i = 1; i < n; i++)
        printf("%d ", dis[i]);
    printf("%d\n", dis[n]);
    return 0;
}

2021/7/27更新

ps:对于dijkstra我选择是用vector 来存边和权值,然后是选择使用优先队列来优化的,但是因为优先队列默认是大根堆,就是大的在前面,所以我选择了greater使用小根堆,然后最开始第一个存的是点,第二个存的是距离,我确实是个逆天了。

看了好一会儿才想起来,优先队列的排序是优先排第一个数,然后如果第一个相同再排第二个,因为我距离是在第二个的,所以,我最开始出来的点不一定是距离最小的点,而一定是序号最小的点,确实是个逆天了

新的代码:

#include<bits/stdc++.h>
using namespace std;
#define ll  long long
#define ull unsigned long long
#define std std::ios::sync_with_stdio(0)
#define mem(a,b) memset(a,b,sizeof(a));
#define P pair<int,int>
const int INF = 0x3f3f3f3f-1;
const int inf = 2147483647;
const int maxn = 5e5 + 10;
struct edge
{
	int to, w;
};
vector<edge>a[maxn];            //这里是需要开一个一维的vector
int n, m, s;
int vis[maxn];
ll dis[maxn];
void dijkstra()
{
	priority_queue<P, vector<P>, greater<P> >q;
	q.push({ 0,s });        //经典pair第一个存的是距离第二个存的是点
	dis[s] = 0;          
	while (!q.empty())
	{
		int u = q.top().second;
		q.pop();
		if (vis[u])
			continue;
		vis[u] = 1;
		for (int i = 0; i < a[u].size(); i++)
		{
			int v = a[u][i].to;
			if (dis[u] + a[u][i].w < dis[v])
			{
				dis[v] = dis[u] + a[u][i].w;
			}
			if(!vis[v])
				q.push({ dis[v],v });

		}
	}
}

int main()
{
	std;
	cin >> n >> m >> s;
	for (int i = 0; i < m; i++)
	{
		int u, v, w;
		cin >> u >> v >> w;
		a[u].push_back({ v,w });
	}

	mem(vis, 0);
	for (int i = 0; i <= n; i++)
		dis[i] = inf;
	dijkstra();

	for (int i = 1; i <n; i++)
		cout << dis[i] << " ";
	cout << dis[n] << '\n';
	return 0;
}

感觉过了没有一个月,码风变化还是挺大的,哈哈哈

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值