对有向图,无向图均有效。要求,权值为正。
贪心。每次取距离s最近的点,来更新其他点。
BFS。将权值看成单位长度的路径之和,最近的点即BFS最先达到的点。
定义delta(u,v),若u,v不可达,值为无穷。若u,v可达,则delta(u,v) 即u,v间最短距离。
松弛操作:
RELAX(u,v,w)
if d[u] > d[v] + w(u,v)
then d[u] = d[v] + w(u,v)
parent[v] = u
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespacestd;
const int maxn =10005;
const int INF =1 << 20;
struct edge{
int v,w;
};
typedef pair<int,int> pr;// delta[i] i
int d[maxn];//初始化为无限,依次更新,至达到delta(u)。//类似并查集中f[x] 和 find(int x)的关系,需要更新。//不同的是并查集find(x)需要通过f[x]来得到,f[x]的值可能是该树根节点,也可能只是该树x节点的某个祖先。而d[u]一开始被初始化为INF,通过遍历更新,可以证明,最后可以达到真实值,即delta(u),而在中间过程,不一定为最小值delta(u)
void dijkstra(int s,int n,vector<edge> mp[maxn])
{
for (int i =1; i <= n; i ++) {
d[i] =INF;
}
d[s] =0;
priority_queue<pr,vector<pr>,greater<pr> >pq;
pq.push(pr{d[s],s} );
while (!pq.empty()) {
pr p = pq.top();
pq.pop();
int th = p.second;
if (d[th] >= p.first) {//如果此时d[i]中存的值,不小于,真实i点到起点到距离,即delta(s,i),那么就更新
for (int i =0; i < mp[th].size() ; i ++) {
edge &e = mp[th][i];
if (d[e.v] >d[th] + e.w) {
d[e.v] =d[th] + e.w;
pq.push(pr {d[e.v],e.v});//bfs
}
}
}
}
}
int main()
{
int n,m;
while (cin >> n >> m) {
if (n ==0 && m == 0) {
return0;
}
int a,b,c;
vector<edge> mp[maxn];// u v w
for (int i =0; i < m; i ++) {
scanf("%d %d %d",&a,&b,&c);
mp[a].push_back(edge{b,c});
mp[b].push_back(edge{a,c});
}
dijkstra(1, n, mp);
cout <<d[n] << endl;
}
return0;
}