题目链接:【模板】单源最短路径(标准版) - 洛谷
题目背景
2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路。
然后呢?
100 \rightarrow 60100→60;
\text{Ag} \rightarrow \text{Cu}Ag→Cu;
最终,他因此没能与理想的大学达成契约。
小 F 衷心祝愿大家不再重蹈覆辙。
题目描述
给定一个 nn 个点,mm 条有向边的带非负权图,请你计算从 ss 出发,到每个点的距离。
数据保证你能从 ss 出发到任意点。
输入格式
第一行为三个正整数 n, m, sn,m,s。 第二行起 mm 行,每行三个非负整数 u_i, v_i, w_iui,vi,wi,表示从 u_iui 到 v_ivi 有一条权值为 w_iwi 的有向边。
输出格式
输出一行 nn 个空格分隔的非负整数,表示 ss 到每个点的距离。
输入输出样例
输入 #1复制
4 6 1 1 2 2 2 3 2 2 4 1 1 3 5 3 4 3 1 4 4
输出 #1复制
0 2 4 3
说明/提示
样例解释请参考 数据随机的模板题。
1 \leq n \leq 10^51≤n≤105;
1 \leq m \leq 2\times 10^51≤m≤2×105;
s = 1s=1;
1 \leq u_i, v_i\leq n1≤ui,vi≤n;
0 \leq w_i \leq 10 ^ 90≤wi≤109,
0 \leq \sum w_i \leq 10 ^ 90≤∑wi≤109。
本题数据可能会持续更新,但不会重测,望周知。
2018.09.04 数据更新 fr
解题思路:
这题主要是dijkstra算法+优化。刚开始使用邻接矩阵建图,可想而知在大量数据下超时了。后面去学习了一下链式前向星(观看是博客主m_little horse的文章,非常细致,平生第一次看懂了链式前向星,推荐大家去看。文章链接:http://t.csdn.cn/veqjp),用优先队列存储中间点。正当我觉得一切都很完美的时候,超时给我来了重重一锤。(陷入沉思:为啥还超时,都优化成这样了,是不是数据太刁钻了)不信邪,去看了大家ac的代码,发现输入输出都是用scanf()和printf()。cin和cout用久了,都忘记了它的时间消耗太大了。改完后过了几个测试点,还有几个一直超时。发现数组长度开小了,最最最后终于过了。
注意事项总结:1、链式前向星建图,优先队列存储中间点
2、输入输出用scanf()和printf()。不要用cin和cout会超时
3、数组长度一定要看清题目所给范围,不要开小了
AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,s;
const int MaxN=100010,MaxM=200010,Max=0x7fffffff;
int head[100005],cnt=0;
int dis[MaxN],vis[MaxN];
struct edge{
int v;//终点
int w;//权值
int next;//下一条边
};
edge e[MaxM];
struct cmp{
bool operator()(edge a,edge b){
return a.w>b.w;//排序法则与sort相反
}
};
void add(int u,int v,int w){//加边
++cnt;
e[cnt].v=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt;
}
void dijkstra(){
priority_queue<edge,vector<edge>,cmp > pq;
int v,w,f;
edge tmp;
pq.push({s,0,-1});
while(!pq.empty()){
tmp=pq.top();
v=tmp.v;
pq.pop();
if(vis[v]!=0) continue;
vis[v]=1;
f=v;
for(int i=head[f];i!=-1;i=e[i].next){
v=e[i].v;
w=e[i].w;
if(dis[v]>dis[f]+w){
dis[v]=dis[f]+w;
if(vis[v]==0)pq.push({v,dis[v],head[f]});
//cout<<i<<","<<s<<"->"<<f<<"->"<<v<<":"<<w<<","<<dis[v]<<endl;
}
}
}
}
int main(){
scanf("%d%d%d",&n,&m,&s);
int u,v,w;
for(int i=1;i<=n;i++){
head[i]=-1;
vis[i]=0;
dis[i]=Max;
}
dis[s]=0;
while(m--){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
dijkstra();
for(int i=1;i<=n;i++){
printf("%d ",dis[i]);
}
return 0;
}