POJ 1511 - Invitation Cards (dijkstra优先队列)
题目链接:http://poj.org/problem?id=1511
就是求从起点到其他点的最短距离加上其他点到起点的最短距离的和 , 注意路是单向的.
因为点和边很多, 所以用dijkstra优先队列的做法.
起点到其他点的最短距离之和就是dij一下 . 要求其他点到起点的最短距离的话就是把原先边的方向反向一下,然后再求起点到其他点的最短距离之和 , 同样dij一下.
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <queue> 6 7 using namespace std; 8 const int MAXN = 1e6 + 5; 9 typedef long long LL; 10 typedef pair <LL , LL> P; 11 vector <P> edge[MAXN]; //这里邻接表二元组(pair)的second代表边的终点标号, first代表边的距离 12 bool ok[MAXN]; 13 LL d[MAXN] , INF = 1e12; 14 int a[MAXN] , b[MAXN] , c[MAXN]; //分别代表边的起点 终点 权值 15 16 void init(int n) { 17 for(int i = 1 ; i <= n ; i++) { 18 d[i] = INF; 19 ok[i] = false; 20 edge[i].clear(); 21 } 22 } 23 24 void dijkstra(int s) { 25 d[s] = 0; 26 priority_queue <P , vector<P> , greater<P> > Q; //优先队列 二元组的first:最短距离 second:点的标号 27 Q.push(P(0 , s)); //压入起点 28 while(!Q.empty()) { 29 P p = Q.top(); 30 Q.pop(); 31 int v = p.second; 32 if(ok[v]) { 33 continue; 34 } 35 ok[v] = true; 36 for(int i = 0 ; i < edge[v].size() ; i++) { 37 P temp = edge[v][i]; 38 if(d[temp.second] > d[v] + temp.first) { 39 d[temp.second] = d[v] + temp.first; 40 Q.push(P(d[temp.second] , temp.second)); 41 } 42 } 43 } 44 } 45 46 int main() 47 { 48 int t , n , m; 49 LL u , v , cost; 50 scanf("%d" , &t); 51 while(t--) { 52 scanf("%d %d" , &n , &m); 53 init(n); 54 for(int i = 0 ; i < m ; i++) { 55 scanf("%d %d %d" , &a[i] , &b[i] , &c[i]); 56 edge[a[i]].push_back(P(LL(c[i]) , LL(b[i]))); 57 } 58 LL res = 0; 59 dijkstra(1); 60 for(int i = 2 ; i <= n ; i++) { 61 res += d[i]; 62 } 63 init(n); 64 for(int i = 0 ; i < m ; i++) { 65 edge[b[i]].push_back(P(LL(c[i]) , LL(a[i]))); //每条边反向一下 66 } 67 dijkstra(1); 68 for(int i = 2 ; i <= n ; i++) { 69 res += d[i]; 70 } 71 printf("%lld\n" , res); 72 } 73 }