题目:
You are given a weighted undirected graph. The vertices are enumerated from 1 to n. Your task is to find the shortest path between the vertex 1 and the vertex n.
The first line contains two integers n and m (2 ≤ n ≤ 105, 0 ≤ m ≤ 105), where n is the number of vertices and m is the number of edges. Following m lines contain one edge each in form ai, bi and wi (1 ≤ ai, bi ≤ n, 1 ≤ wi ≤ 106), where ai, bi are edge endpoints and wi is the length of the edge.
It is possible that the graph has loops and multiple edges between pair of vertices.
Write the only integer -1 in case of no path. Write the shortest path in opposite case. If there are many solutions, print any of them.
5 6 1 2 2 2 5 5 2 3 4 1 4 1 4 3 3 3 5 1
1 4 3 5
5 6 1 2 2 2 5 5 2 3 4 1 4 1 4 3 3 3 5 1
1 4 3 5
代码:
尽管图中可能有自环和多重边,但不会出现负环,因此dijkstra依然可用 负环需要使用Bellman-Ford
实现的时候有几个细节需要留心:
起始点到某些结点的最小距离会超出int范围;
memset()和fill()不要混用,使用fill()时第二个参数的含义是连续多少个空间进行初始化,所以从0开始的时候需要写成n+1
#include<bits/stdc++.h>
#include<queue>
using namespace std;
const int maxn=1e5+30;
const __int64 inf=(__int64)1<<62;//0x3f3f3f3f 太小了....
typedef pair<__int64,int> p;//<a,b> 起点到b的最短距离为a
struct edge {
int to;
int cost;
edge(int tto=0,int ccost=0):to(tto),cost(ccost){}
};
int n,m;
__int64 d[maxn];
int prev[maxn];
vector<edge> g[maxn];
void dijkstra(int s) {
priority_queue<p,vector<p>,greater<p> >qu;//堆按照p的first(最短距离)排序,小顶堆
fill(d,d+n+1,inf);
fill(prev,prev+n+1,-1);//+n 太小了...
// memset(prev,sizeof(prev),-1);//混用会报错
d[s]=0;
qu.push(p(0,s));//从起点出发到顶点s的最短距离为0
while(!qu.empty()) {
p temp=qu.top();
qu.pop();
int tmpv=temp.second;
if(temp.first>d[tmpv]) continue;//跳过更新过程中入队的非最小值
for(int i=0;i<g[tmpv].size();++i) {//遍历该顶点连出的每条边
edge e=g[tmpv][i];
if(d[e.to]>d[tmpv]+e.cost) {
d[e.to]=d[tmpv]+(__int64)e.cost;
prev[e.to]=tmpv;
qu.push(p(d[e.to],e.to));
}
}
}
}
vector<int> getpath(int t) {//s -> t
vector<int> path;
while(t!=-1) {//从 t 倒着走,一直走到 s
path.push_back(t);
t=prev[t];
}
reverse(path.begin(),path.end());
return path;
}
int main() {//78ms 6400kb
int a,b,c;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;++i) {
g[i].clear();
}
for(int i=1;i<=m;++i) {
scanf("%d%d%d",&a,&b,&c);
g[a].push_back(edge(b,c));
g[b].push_back(edge(a,c));
}
dijkstra(1);
if(d[n] == inf) puts("-1");
else {
vector<int> pt = getpath(n);
vector<int>::iterator it=pt.begin();
printf("%d",*it);
++it;
for(; it!=pt.end(); it++) printf(" %d",*it);
puts("");
}
return 0;
}
或者一开始d[]初始化为-1,第34行改为if((d[e.to]>d[tmpv]+e.cost)||d[e.to]==-1),第66行改为if(d[n] == -1) puts("-1");,也可以。