P3371&P4779 dijk板子

题目大意

2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路。
然后呢?
100→60;最终,他因此没能与理想的大学达成契约。
小 F 衷心祝愿大家不再重蹈覆辙。
题目描述 给定一个 n 个点,m 条有向边的带非负权图,请你计算从 sss 出发,到每个点的距离。
数据保证你能从 s 出发到任意点。
输入格式 第一行为三个正整数 n,m,s。
第二行起 m 行,每行三个非负整数 u_i, v_i, w_i​,表示从 u_i​ 到 v_i​ 有一条权值为 w_i​ 的有向边。
输出格式 输出一行 n 个空格分隔的非负整数,表示 s 到每个点的距离。

思路

不说了,上板子(纪念我从入坑洛谷起写了1年整的纯板子)

code:

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
int b[101001],e=1,first[101001];
struct f{
	int b;
	int d;
	int net;
} a[510001];
bool book[101001];
struct f2{
	int x,y;
} p;
bool operator <(const f2 &x,const f2 &y)
{
	return x.x>y.x;
}
priority_queue<f2> c;
void jb(int x,int y,int z)
{
	a[e].b=y;
	a[e].d=z;
	a[e].net=first[x];
	first[x]=e;
	e++;
}
int n,m,q;
void dij()
{
	memset(b,0x3f,sizeof(b));
	memset(book,0,sizeof(book));
	b[q]=0;
	p.x=0,p.y=q;
	c.push(p);
	for (int j=1;j<n;j++)
	{
		while (book[c.top().y]&&c.size()>1) c.pop();
		f2 xx=c.top();
		c.pop();
		int u=xx.y;
		if (book[u]) continue;
		book[u]=1;
		for (int i=first[u];i!=0;i=a[i].net)
		{
			if (a[i].d+b[u]<b[a[i].b])
			{
				b[a[i].b]=a[i].d+b[u];
				p.x=b[a[i].b];
				p.y=a[i].b;
				c.push(p);
			}
		}
	}
	b[q]=0;
	p.x=0,p.y=q;
	c.push(p);
	for (int j=1;j<n;j++)
	{
		while (book[c.top().y]&&c.size()>1) c.pop();
		f2 xx=c.top();
		c.pop();
		int u=xx.y;
		book[u]=1;
		for (int i=first[u];i!=0;i=a[i].net)
		{
			if (a[i].d+b[u]<b[a[i].b])
			{
				b[a[i].b]=a[i].d+b[u];
				p.x=b[a[i].b];
				p.y=a[i].b;
				c.push(p);
			}
		}
	}
}
int main()
{
	cin>>n>>m>>q;
	int x,y,z;
	for (int i=1;i<=m;i++)
	{
		cin>>x>>y>>z;
		jb(x,y,z);
	}
	dij();
	for (int i=1;i<=n;i++) cout<<b[i]<<' '; 
	return 0;
}//好人一生平安
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值