题目:
http://acm.hdu.edu.cn/showproblem.php?pid=1535
题意:
有向图,求点1到点2-n的最短距离之和以及点2-n到点1的最短距离之和
方法:
1、跑1为原点的最短路
2、反向建图(把有向图的边反向,(u,v,w)变成(v,u,w)),跑1为原点的最短路
3、将两者距离之和加和即可(注意用 long long ,int会溢出)
1 void input() 2 { 3 scanf("%d%d", &n, &m); 4 g1.init(n); 5 g2.init(n); 6 for (int i = 0; i < m; i++) 7 { 8 int u, v, w; 9 scanf("%d%d%d", &u, &v, &w); 10 g1.addse(u, v, w); 11 g2.addse(v, u, w); 12 } 13 } 14 void solve() 15 { 16 g1.spfa(1); 17 g2.spfa(1); 18 LL ans = 0; 19 for (int i = 1; i <= n; i++) 20 ans += g1.d[i], ans += g2.d[i]; 21 printf("%I64d ", ans); 22 }
加SLF优化的SPFA:
设队列队首元素为x,目前元素为v,若d[v]<d[x]则将v插入队列首,否则插入队列尾
1 /** 2 *含负权值加权图的单源最短路径:Spfa 算法(稀疏图)(O(KE))(不适用分层图)(SLF优化的SPFA) 3 *输入:图(链式前向星),n(顶点数,从1到n) 4 *输出:d[](距离) 5 */ 6 const int maxn = 0; 7 const int maxm = 0; 8 struct Edge 9 { 10 int u, v, w; 11 int next; 12 } edge[maxm]; 13 int head[maxn], en; 14 int n, m; 15 int d[maxn]; 16 int pre[maxn];//用于解析路径 17 int cnt[maxn]; 18 bool mark[maxn]; 19 deque<int> Q; 20 void addse(int u, int v, int w) 21 { 22 edge[en].u = u; 23 edge[en].v = v; 24 edge[en].w = w; 25 edge[en].next = head[u]; 26 head[u] = en++; 27 } 28 void init() 29 { 30 memset(head, -1, sizeof(head)); 31 en = 0; 32 } 33 /*DFS找负环 34 bool cir[maxn]; 35 void dfs(int u) 36 { 37 cir[u]=true; 38 for(int i=head[u]; i!=-1; i=edge[i].next) 39 if(!cir[edge[i].v]) dfs(edge[i].v); 40 } 41 */ 42 bool spfa(int s) 43 { 44 memset(d, 0x3f, sizeof(int) * (n + 1)); 45 for (int i = 1; i <= n; ++i) pre[i] = i; //用于解析路径 46 memset(mark, 0, sizeof(bool) * (n + 1)); 47 memset(cnt, 0, sizeof(int) * (n + 1)); 48 d[s] = 0; 49 Q.push_back(s); 50 mark[s] = 1; 51 cnt[s]++; 52 while (Q.size()) 53 { 54 int u = Q.front(); 55 Q.pop_front(); 56 mark[u] = 0; 57 for (int i = head[u]; i != -1; i = edge[i].next) 58 { 59 int v = edge[i].v; 60 int w = edge[i].w; 61 if (d[u] + w < d[v]) 62 { 63 pre[v] = u; // 用于解析路径 64 d[v] = d[u] + w; 65 if (mark[v] == 0) 66 { 67 mark[v] = 1; 68 if (!Q.empty()) 69 { 70 if (d[v] > d[Q.front()]) Q.push_back(v); 71 else Q.push_front(v); 72 } 73 else Q.push_back(v); 74 if (++cnt[v] > n) return false; //有负环,可以用DFS找 75 } 76 } 77 } 78 } 79 return true; 80 }
代码:加SLF优化的SPFA最短路
1 /******************************************** 2 *ACM Solutions 3 * 4 *@Title: 5 *@Version: 1.0 6 *@Time: 2014-xx-xx 7 *@Solution: http://www.cnblogs.com/xysmlx/p/xxxxxxx.html 8 * 9 *@Author: xysmlx(Lingxiao Ma) 10 *@Blog: http://www.cnblogs.com/xysmlx 11 *@EMail: xysmlx@163.com 12 * 13 *Copyright (C) 2011-2015 xysmlx(Lingxiao Ma) 14 ********************************************/ 15 // #pragma comment(linker, "/STACK:102400000,102400000") 16 #include <cstdio> 17 #include <iostream> 18 #include <cstring> 19 #include <string> 20 #include <cmath> 21 #include <set> 22 #include <list> 23 #include <map> 24 #include <iterator> 25 #include <cstdlib> 26 #include <vector> 27 #include <queue> 28 #include <stack> 29 #include <algorithm> 30 #include <functional> 31 using namespace std; 32 typedef long long LL; 33 #define pb push_back 34 #define ROUND(x) round(x) 35 #define FLOOR(x) floor(x) 36 #define CEIL(x) ceil(x) 37 const int maxn = 1000010; 38 const int maxm = 2000010; 39 const int inf = 0x3f3f3f3f; 40 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL; 41 const double INF = 1e30; 42 const double eps = 1e-6; 43 const int P[4] = {0, 0, -1, 1}; 44 const int Q[4] = {1, -1, 0, 0}; 45 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1}; 46 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1}; 47 48 struct SPFA 49 { 50 struct Edge 51 { 52 int u, v, w; 53 int next; 54 } edge[maxm]; 55 int head[maxn], en; 56 int n, m; 57 int d[maxn]; 58 int cnt[maxn]; 59 int mark[maxn]; 60 deque<int> Q; 61 int pre[maxn];//用于解析路径 62 void addse(int u, int v, int w) 63 { 64 edge[en].u = u; 65 edge[en].v = v; 66 edge[en].w = w; 67 edge[en].next = head[u]; 68 head[u] = en++; 69 } 70 void init(int _n) 71 { 72 n = _n; 73 memset(head, -1, sizeof(head)); 74 en = 0; 75 while (!Q.empty()) Q.pop_back(); 76 } 77 78 /*DFS找负环 79 bool cir[maxn]; 80 void dfs(int u) 81 { 82 cir[u]=true; 83 for(int i=head[u]; i!=-1; i=edge[i].next) 84 if(!cir[edge[i].v]) dfs(edge[i].v); 85 } 86 */ 87 bool spfa(int s) 88 { 89 for (int i = 1; i <= n; ++i) d[i] = inf; 90 for (int i = 1; i <= n; ++i) pre[i] = i; //用于解析路径 91 memset(mark, 0, sizeof(mark)); 92 memset(cnt, 0, sizeof(cnt)); 93 d[s] = 0; 94 Q.push_back(s); 95 mark[s] = 1; 96 cnt[s]++; 97 while (Q.size()) 98 { 99 int u = Q.front(); 100 Q.pop_front(); 101 mark[u] = 0; 102 for (int i = head[u]; i != -1; i = edge[i].next) 103 { 104 int v = edge[i].v; 105 int w = edge[i].w; 106 if (d[u] + w < d[v]) 107 { 108 pre[v] = u; // 用于解析路径 109 d[v] = d[u] + w; 110 if (mark[v] == 0) 111 { 112 mark[v] = 1; 113 if (!Q.empty()) 114 { 115 if (d[v] > d[Q.front()]) Q.push_back(v); 116 else Q.push_front(v); 117 } 118 else Q.push_back(v); 119 if (++cnt[v] > n) return false; //有负环,可以用DFS找 120 } 121 } 122 } 123 } 124 return true; 125 } 126 } g1, g2; 127 128 int kase; 129 int n, m; 130 void init() 131 { 132 kase++; 133 } 134 void input() 135 { 136 scanf("%d%d", &n, &m); 137 g1.init(n); 138 g2.init(n); 139 for (int i = 0; i < m; i++) 140 { 141 int u, v, w; 142 scanf("%d%d%d", &u, &v, &w); 143 g1.addse(u, v, w); 144 g2.addse(v, u, w); 145 } 146 } 147 void debug() 148 { 149 // 150 } 151 void solve() 152 { 153 g1.spfa(1); 154 g2.spfa(1); 155 LL ans = 0; 156 for (int i = 1; i <= n; i++) 157 ans += g1.d[i], ans += g2.d[i]; 158 printf("%I64d ", ans); 159 } 160 void output() 161 { 162 // 163 } 164 int main() 165 { 166 // int size = 256 << 20; // 256MB 167 // char *p = (char *)malloc(size) + size; 168 // __asm__("movl %0, %%esp " :: "r"(p)); 169 170 // std::ios_base::sync_with_stdio(false); 171 #ifdef xysmlx 172 freopen("in.cpp", "r", stdin); 173 #endif 174 175 kase = 0; 176 int T; 177 scanf("%d", &T); 178 while (T--) 179 { 180 init(); 181 input(); 182 solve(); 183 output(); 184 } 185 return 0; 186 }