dijkstra算法的思路:
(1)找到最短距离已经确定的顶点,从它出发更新相邻顶点的最短距离
(2)此后不再关心(1)中最短距离已经确定的顶点
最开始时只有起点的最短距离是确定的,而在未使用过的顶点中,距离d[i]最小的顶点就是最短距离已经确定的顶点,在不存在负边的情况下d[i]不会在之后的更新中变小。 存在负边则无法使用dijkstra
使用优先队列实现:
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 1000+50;
const int INF=100000;
class HeapNode{
public:
int d,u;
bool operator <(const HeapNode & rhs) const{
return d>rhs.d;
}
};
class Edge {
public:
int to,dist;
Edge(int to=0,int dist=0):to(to),dist(dist){}
};
vector<Edge>G[maxn];
int d[maxn];
bool done[maxn];
void dijkstra(int s){
priority_queue<HeapNode> Q;
for(int i=0;i<maxn;i++)d[i]=INF;
d[s]=0;
memset(done,0,sizeof(done));
Q.push((HeapNode){0,s});
while(!Q.empty()){
HeapNode x=Q.top();Q.pop();
int u=x.u;
if(done[u])continue;
done[u]=true;
for(int i=0;i<G[u].size();i++){
Edge& e=G[u][i];
if(d[e.to]>d[u]+e.dist){
d[e.to]=d[u]+e.dist;
Q.push((HeapNode){d[e.to],e.to});
}
}
}
}
int main(){
//freopen("datain.txt","r",stdin);
int T,S,D;
while(~scanf("%d%d%d",&T,&S,&D)){
int ans=INF;
for(int i=0;i<maxn;i++)
G[i].clear();
for(int i=0;i<T;i++){
int from,to,dist;
scanf("%d%d%d",&from,&to,&dist);
G[from].push_back(Edge(to,dist));
G[to].push_back(Edge(from,dist));
}
for(int i=0;i<S;i++){
int source;
scanf("%d",&source);
G[0].push_back(Edge(source,0));
G[source].push_back(Edge(0,0));
}
int dest[maxn];
for(int i=0;i<D;i++)
scanf("%d",&dest[i]);
dijkstra(0);
for(int i=0;i<D;i++)
ans=min(ans,d[dest[i]]);
printf("%d\n",ans);
}
}
而图中存在负边的情况,则需要使用Bellman-Ford或者Floyd-Warshall算法
Bellman-Ford:
#include<cstdio>
#include <iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#define INF 1000000
const int maxn = 1000 + 5;
using namespace std;
int d[maxn];//最短距离
int V, E;//顶点数 边数
struct edge{
int from, to, cost;
}edges[maxn];
void shortest_path(int s) {
for (int i = 0;i < V;i++) d[i] = INF;
d[s] = 0;
while (true) {
bool update = false;
for (int i = 0;i < E;i++) {
edge e = edges[i];
if (d[e.from] != INF && d[e.to] > d[e.from] + e.cost) {
d[e.to] = d[e.from] + e.cost;
update = true;
}
}
if (!update)break;
}
}
bool find_negative_loop() {
memset(d, 0, sizeof(d));
for (int i = 0;i < V;i++) {
for (int j = 0;j < E;j++) {
edge e = edges[j];
if (d[e.to] > d[e.from] + e.cost) {
d[e.to] = d[e.from] + e.cost;
if (i == V - 1)return true;//第V次仍然更新了
}
}
}return false;
}