ACM/ICPC 之 最短路-SPFA+正逆邻接表(POJ1511(ZOJ2008))
求单源最短路到其余各点,然后返回源点的总最短路长,以构造邻接表的方法不同分为两种解法。
POJ1511(ZOJ2008)-Invitation Cards
改变构造邻接表的方法后,分为两种解法
解法一:
1 //POJ1511-ZOJ2008 2 //Time:7766Ms Memory:99112K 3 //求从1处到各点后再返回1处的最短总路长 4 //需要构造邻接表和逆邻接表 5 //构造方法1:vector构造邻接表 6 //SPFA+邻接表 7 #include<iostream> 8 #include<cstring> 9 #include<cstdio> 10 #include<vector> 11 #include<queue> 12 using namespace std; 13 14 #define MAX 1000005 15 #define INF 0x3f3f3f3f 16 17 struct Edge { 18 int u, w; 19 Edge(int uu, int ww) :u(uu), w(ww) {} 20 }; 21 22 vector<Edge> e1[MAX], e2[MAX]; //邻接表-逆邻接表 23 24 int n, m; 25 int d[MAX]; 26 long long sum; 27 bool v[MAX]; 28 29 void SPFA(int x, vector<Edge> e[MAX]) 30 { 31 memset(d, INF, sizeof(d)); 32 memset(v, false, sizeof(v)); 33 queue<int> q; 34 q.push(x); 35 d[x] = 0; 36 while (!q.empty()){ 37 int cur = q.front(); 38 q.pop(); 39 v[cur] = false; 40 for (int i = 0; i < e[cur].size(); i++) 41 { 42 int u = e[cur][i].u; 43 if (d[u] > d[cur] + e[cur][i].w) 44 { 45 d[u] = d[cur] + e[cur][i].w; 46 if (!v[u]) { q.push(u); v[u] = true; } 47 } 48 } 49 } 50 for (int i = 2; i <= n; i++) 51 sum += d[i]; 52 } 53 54 int main() 55 { 56 int T; 57 scanf("%d", &T); 58 while (T--) { 59 sum = 0; 60 memset(e1, 0, sizeof(e1)); 61 memset(e2, 0, sizeof(e2)); 62 scanf("%d%d", &n, &m); 63 while (m--) { 64 int u, v, w; 65 scanf("%d%d%d", &u, &v, &w); 66 e1[u].push_back(Edge(v, w)); //正向 67 e2[v].push_back(Edge(u, w)); //逆向 68 } 69 70 SPFA(1, e1); 71 SPFA(1, e2); 72 printf("%lld\n", sum); 73 } 74 75 return 0; 76 }
解法二:
1 //POJ1511-ZOJ2008 2 //Time:2000Ms Memory:36424K 3 //求从1处到各点后再返回1处的最短总路长 4 //需要构造邻接表和逆邻接表 5 //构造方法2:偏序关系构造邻接表 6 //SPFA+邻接表 7 #include<iostream> 8 #include<cstring> 9 #include<cstdio> 10 #include<vector> 11 #include<queue> 12 using namespace std; 13 14 #define MAX 1000005 15 #define INF 0x3f3f3f3f 16 17 struct Edge { 18 int u, w, next; 19 Edge() {} 20 Edge(int uu, int ww, int nn) :u(uu), w(ww), next(nn) {} 21 }e1[MAX], e2[MAX]; //邻接表-逆邻接表 22 23 int h1[MAX], h2[MAX]; //正表表头-逆表表头 24 int n, m; 25 int d[MAX]; 26 long long sum; 27 bool v[MAX]; 28 29 void SPFA(int x, Edge e[MAX], int h[MAX]) 30 { 31 memset(d, INF, sizeof(d)); 32 memset(v, false, sizeof(v)); 33 queue<int> q; 34 q.push(x); 35 d[x] = 0; 36 while (!q.empty()){ 37 int cur = q.front(); 38 q.pop(); 39 v[cur] = false; 40 for (int i = h[cur]; i != -1; i = e[i].next) 41 { 42 int u = e[i].u; 43 int w = e[i].w; 44 if (d[u] > d[cur] + w) 45 { 46 d[u] = d[cur] + w; 47 if (!v[u]) { q.push(u); v[u] = true; } 48 } 49 } 50 } 51 for (int i = 2; i <= n; i++) 52 sum += d[i]; 53 } 54 55 int main() 56 { 57 int T; 58 scanf("%d", &T); 59 while (T--) { 60 sum = 0; 61 memset(e1, 0, sizeof(e1)); 62 memset(e2, 0, sizeof(e2)); 63 memset(h1, -1, sizeof(h1)); 64 memset(h2, -1, sizeof(h2)); 65 scanf("%d%d", &n, &m); 66 for (int i = 0; i < m; i++) { 67 int u, v, w; 68 scanf("%d%d%d", &u, &v, &w); 69 e1[i] = Edge(v, w, h1[u]); 70 e2[i] = Edge(u, w, h2[v]); 71 h1[u] = h2[v] = i; 72 } 73 74 SPFA(1, e1, h1); 75 SPFA(1, e2, h2); 76 printf("%lld\n", sum); 77 } 78 79 return 0; 80 }
他坐在湖边,望向天空,她坐在对岸,盯着湖面