题目:洛谷P1339 [USACO09OCT]Heat Wave G
题目描述
有一个 n n n 个点 m m m 条边的无向图,请求出从 s s s 到 t t t 的最短路长度。
输入格式
第一行四个正整数
n
,
m
,
s
,
t
n,m,s,t
n,m,s,t。
接下来
m
m
m 行,每行三个正整数
u
,
v
,
w
u,v,w
u,v,w,表示一条连接
u
,
v
u,v
u,v,长为
w
w
w 的边。
输出格式
输出一行一个整数,表示答案。
样例输入
7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1
样例输出
7
提示
【数据范围】
对于
100
%
100\%
100% 的数据,
1
≤
n
≤
2500
1\le n \le 2500
1≤n≤2500,
1
≤
m
≤
6200
1\le m \le 6200
1≤m≤6200,
1
≤
w
≤
1000
1\le w \le 1000
1≤w≤1000。
【样例说明】
5
→
6
→
1
→
4
5 \to 6 \to 1 \to 4
5→6→1→4 为最短路,长度为
3
+
1
+
3
=
7
3+1+3 = 7
3+1+3=7。
普通版Dijkstra
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define NOTLE ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl '\n'
#define T int TT;cin >> TT;while (TT--)
#define lint long long
#define pb push_back
#define eb emplace_back
int n,m,s,t;
int ne[20010],last[20010],to[20010],w[20010],cnt=0;
int b[20010]={0},vis,d[20010]; //b标记是否经过该点,d存路程
void add(int x,int y,int z){ //链式前向星存图
to[++cnt]=y; //to存终点
ne[cnt]=last[x]; //ne存该出发点上一条边
last[x]=cnt; //last存该出发点最后一条边
w[cnt]=z; //w存边权
}
int main(){
NOTLE;
cin >> n >> m >> s >> t;
for(int i=1;i<=n;i++) d[i]=INF; //初始化将到达每个点的路程设为无穷大
for(int i=1;i<=m;i++){
int u,v,x;
cin >> u >> v >> x;
add(u,v,x); //无向图正反都存一遍
add(v,u,x);
}
vis=s;
d[s]=0;
while(!b[vis]){ //dijkstra
b[vis]=1;
for(int i=last[vis];i;i=ne[i])
if(!b[to[i]] && d[to[i]]>d[vis]+w[i])
d[to[i]]=d[vis]+w[i];
int minn=INF;
for(int i=1;i<=n;i++) //查找没有经过的距起点最近的点
if(minn>d[i] && !b[i]) minn=d[i],vis=i;
}
cout << d[t];
return 0;
}
堆优化版Dijkstra
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define NOTLE ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl '\n'
#define T int TT;cin >> TT;while (TT--)
#define lint long long
#define pb push_back
#define eb emplace_back
int n,m,s,t;
int ne[20010],last[20010],to[20010],w[20010],cnt=0;
int b[20010]={0},d[20010]; //b标记是否经过该点,d存路程
priority_queue<pair<int,int>> q; //优先队列,first存路径相反数,second存点
void add(int x,int y,int z){ //链式前向星存图
to[++cnt]=y; //to存终点
ne[cnt]=last[x]; //ne存该出发点上一条边
last[x]=cnt; //last存该出发点最后一条边
w[cnt]=z; //w存边权
}
int main(){
NOTLE;
cin >> n >> m >> s >> t;
for(int i=1;i<=n;i++) d[i]=INF; //初始化将到达每个点的路程设为无穷大
for(int i=1;i<=m;i++){
int u,v,x;
cin >> u >> v >> x;
add(u,v,x); //无向图正反都存一遍
add(v,u,x);
}
d[s]=0;
q.push(make_pair(0,s));
while(!q.empty()){ //dijkstra堆优化
int p=q.top().second;
q.pop();
if(b[p]) continue;
b[p]=1;
for(int i=last[p];i;i=ne[i])
if(!b[to[i]] && d[to[i]]>d[p]+w[i]){
d[to[i]]=d[p]+w[i];
q.push(make_pair(-d[to[i]],to[i]));
}
}
cout << d[t];
return 0;
}