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 }

 

    原文作者:Inkblots
    原文地址: https://www.cnblogs.com/Inkblots/p/5452452.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞