题目大意
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;
}//好人一生平安