题目链接:http://hihocoder.com/problemset/problem/1081
算法主要思路是:将所有节点分为两个集合(已标记节点和未标记节点),已标记节点集合中的所有节点到源节点的最短距离都已经得到。算法主要的工作就是,循环的从未标记节点集合中每次取出一个到源点距离最短的节点放入已标记集合并更新未标记集合中与该节点邻接的节点到源点的距离,直到终节点被标记(单源单宿最短路)或者所有节点都被标记(单源多宿最短路)。
我的代码:
1 #include <iostream> 2 #include <vector> 3 #include <set> 4 #include <cstring> 5 6 using namespace std; 7 8 #define MAXN 1005 9 #define INF 0x7fffffff 10 11 struct edge 12 { 13 int y, w; 14 edge(int _y, int _w):y(_y),w(_w){} 15 }; 16 17 vector<edge> v[MAXN]; 18 int n, m, d[MAXN]; 19 bool vis[MAXN]; 20 21 struct comp 22 { 23 bool operator()(const int &a, const int &b)const 24 { 25 if(d[a]==d[b]) return a<b;//这里需要注意一下 26 return d[a]<d[b]; 27 } 28 }; 29 30 int dijkstra(int s, int t) 31 { 32 for(int i=1; i<=n; ++i) d[i] = INF; 33 d[s] = 0; 34 memset(vis+1, 0, n); 35 set<int, comp> st; 36 for(int i=1; i<=n; ++i) st.insert(i); 37 while(!st.empty()) 38 { 39 int x = *st.begin(); 40 st.erase(x); 41 vis[x] = true; 42 if(x==t) return d[t]; 43 int sz = v[x].size(); 44 for(int i=0; i<sz; ++i) 45 { 46 int y = v[x][i].y, w = v[x][i].w; 47 if(!vis[y]&&d[y]>d[x]+w) 48 { 49 st.erase(y); 50 d[y] = d[x]+w; 51 st.insert(y); 52 } 53 } 54 } 55 } 56 57 int main() 58 { 59 int s, t; 60 while(cin>>n>>m>>s>>t) 61 { 62 for(int i=1; i<=n; ++i) v[i].clear(); 63 while(m--) 64 { 65 int x, y, w; 66 cin>>x>>y>>w; 67 v[x].push_back(edge(y, w)); 68 v[y].push_back(edge(x, w)); 69 } 70 cout<<dijkstra(s, t)<<endl; 71 } 72 return 0; 73 }