HDU 1874 畅通工程续
题目见此:http://acm.hdu.edu.cn/showproblem.php?pid=1874
解题思路:
- 典型的最短路径,用Dijkstra+优先队列优化
- 注意一点:道路是双向的,且两个城市之间可能有多条双向路,但这里我没有预处理,用vector来find一下其实也挺麻烦的,如果重复多的话应该预处理
贴代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #include <iostream> 5 using namespace std; 6 7 const int MAXN = 101; 8 const int INF = 0xfffffff; 9 //pos表示一个点的位置,即城市; 10 //val指一个其他的节点指向这个节点的代价,q中为从起点指向这个节点,eg中为从eg[i]指向这个节点 11 struct Node 12 { 13 int pos, val; 14 Node(int _p, int _v) : pos(_p), val(_v) {} 15 bool operator < (const Node& a) const 16 { 17 return val > a.val; 18 } 19 }; 20 //邻接表:eg[p][i].val表示从第p个城市指向第eg[p][i].pos个城市的价值,i仅仅表示循环变量,无具体意义 21 vector<Node> eg[MAXN]; 22 //dis表示把S内的节点考虑后所能得到的最小距离(固定起点) 23 int dis[MAXN], N, line; 24 bool S[MAXN]; 25 26 void Dijkstra(int start) 27 { 28 memset(S, 0, sizeof(S)); 29 for(int i=0 ; i<=N ; i++) 30 dis[i] = INF; 31 dis[start] = 0; 32 priority_queue<Node> q; //q中保存的是起点指向的候选节点 33 q.push(Node(start, dis[start])); 34 while(!q.empty()) 35 { 36 Node med = q.top(); q.pop(); //med为最小候选节点,min_cand.pos就是“中介节点” 37 if(S[med.pos]) continue; 38 S[med.pos] = 1; 39 for(int i=0 ; i<eg[med.pos].size() ; i++) //这里从0开始,依次考虑中介节点的邻居 40 { 41 Node nei = eg[med.pos][i]; 42 //med.val表示从起点指向med.pos的价值,nei.val表示从med.pos指向nei.pos的价值 43 if(S[nei.pos] == 0 && med.val + nei.val < dis[nei.pos]) //新路径小于旧路径 44 { 45 dis[nei.pos] = med.val + nei.val; 46 q.push(Node(nei.pos, dis[nei.pos])); 47 } 48 } 49 } 50 } 51 52 int main() 53 { 54 while(scanf("%d %d", &N, &line) != EOF) 55 { 56 for(int i=0 ; i<=N ; i++) //用0-N可以同时处理 1至N 或 0至N-1 的情况 57 eg[i].clear(); 58 while(line--) 59 { 60 int p, q, d; 61 scanf("%d %d %d", &p, &q, &d); 62 eg[p].push_back(Node(q, d)); 63 eg[q].push_back(Node(p, d)); 64 } 65 int start, end; 66 scanf("%d %d", &start, &end); 67 Dijkstra(start); 68 if(dis[end] == INF) 69 printf("-1\n"); 70 else 71 printf("%d\n", dis[end]); 72 } 73 }
直接用模板改的,连注释都没去掉