求多个起点多个终点的最短路,与dij求单源最短路相似,将起点集push进入优先队列,终点集标记,最先遇到的就是最短路
------------------------
http://acm.hdu.edu.cn/showproblem.php?pid=6166
在一个集合中找出两个点距离最短,
二进制枚举起点集与终点集,目的是使每个点与其他点不再一个集合当中(巧妙利用二进制位实现)
1 #include <iostream> 2 #include <string.h> 3 #include <queue> 4 using namespace std; 5 6 #define ll long long 7 const int maxn = 100009; 8 const ll INF = 1e18; 9 int n, m, q; 10 int to[maxn], pre[maxn], p[maxn], a[maxn], index; 11 bool vis[maxn], mark[maxn]; 12 ll dis[maxn], w[maxn]; 13 14 struct Node{ 15 int x; 16 ll y; 17 bool operator < (const Node &b) const { 18 return y > b.y; 19 } 20 }; 21 22 priority_queue<Node> pq; 23 24 void init(){ 25 while(!pq.empty()) pq.pop(); 26 for(int i = 0; i <= n; ++i){ 27 vis[i] = mark[i] = false, dis[i] = INF; 28 } 29 } 30 ll Dij(){ 31 while(!pq.empty()){ 32 Node b = pq.top(); pq.pop(); 33 int xx = b.x; 34 if(mark[xx]) return b.y; 35 if(vis[xx]) continue; 36 vis[xx] = true; 37 for(int i = p[xx]; i; i = pre[i]){ 38 int xxx = to[i]; 39 if(!vis[xxx] && dis[xxx] > dis[xx] + w[i]){ 40 dis[xxx] = dis[xx] + w[i]; 41 pq.push(Node{xxx, dis[xxx]}); 42 } 43 } 44 } 45 return INF; 46 } 47 48 void solve(){ 49 ll sum = INF; 50 for(int i = 0; i < 20; ++i){ 51 init(); 52 for(int j = 0; j < q; ++j){ 53 if(a[j] & (1<<i)){ 54 mark[a[j]] = true; 55 }else{ 56 dis[a[j]] = 0; 57 pq.push(Node{a[j], 0}); 58 } 59 } 60 sum = min(sum, Dij()); 61 init(); 62 for(int j = 0; j < q; ++j){ 63 if(a[j] & (1<<i)){ 64 dis[a[j]] = 0; 65 pq.push(Node{a[j], 0}); 66 }else{ 67 mark[a[j]] = true; 68 } 69 } 70 sum = min(sum, Dij()); 71 } 72 printf("%lld\n", sum); 73 } 74 75 int main(){ 76 int t, cas = 1; 77 scanf("%d", &t); 78 while(t--){ 79 index = 1; 80 scanf("%d%d", &n, &m); 81 for(int i = 0; i <= n; ++i) p[i] = 0; 82 int x, y; 83 ll z; 84 for(int i = 0; i < m; ++i){ 85 scanf("%d%d%lld", &x, &y, &z); 86 to[index] = y, w[index] = z, pre[index] = p[x], p[x] = index ++; 87 } 88 scanf("%d", &q); 89 for(int i = 0; i < q; ++i){ 90 scanf("%d", &a[i]); 91 } 92 printf("Case #%d: ", cas++); 93 solve(); 94 } 95 return 0; 96 }
------------------------------------
http://acm.hdu.edu.cn/showproblem.php?pid=2066
spfa
1 #include "iostream" 2 #include <string.h> 3 #include <queue> 4 #include <vector> 5 using namespace std; 6 7 #define ll long long 8 const int maxn = 1010; 9 int n, m, s, t, from, to, snum, tnum; 10 ll T[maxn], val, sum; 11 bool mark[maxn]; 12 vector<int> a[maxn]; 13 vector<ll> b[maxn]; 14 15 void init() { 16 sum = 1e9; 17 for(int i = 0; i < maxn; ++i) { 18 a[i].clear(), b[i].clear(); 19 mark[i] = false; 20 } 21 } 22 23 void add(int x, int y, ll z) { 24 int len = a[x].size(); 25 for(int i = 0; i < len; ++i) { 26 if(a[x][i] == y) { 27 if(z < b[x][i]) b[x][i] = z; 28 return ; 29 } 30 } 31 a[x].push_back(y); 32 b[x].push_back(z); 33 } 34 35 void spfa() { 36 memset(T, 0x3f, sizeof(T)); 37 queue<int> q; 38 for(int i = 0; i < snum; ++i) { 39 scanf("%d", &to); 40 T[to] = 0; 41 mark[to] = true; 42 q.push(to); 43 } 44 while(!q.empty()) { 45 int k = q.front(); 46 q.pop(); 47 mark[k] = false; 48 for(int i = 0; i < a[k].size(); i++) if(T[k] + b[k][i] < T[a[k][i]]) { 49 T[a[k][i]] = T[k] + b[k][i]; 50 if(!mark[a[k][i]]) { 51 q.push(a[k][i]); 52 mark[a[k][i]] = true; 53 } 54 } 55 } 56 for(int i = 0; i < tnum; ++i){ 57 scanf("%d", &to); 58 if(T[to] < sum) sum = T[to]; 59 } 60 } 61 62 int main() { 63 #ifdef wenbao 64 freopen("in", "r", stdin); 65 #endif 66 while(~scanf("%d%d%d", &m, &snum, &tnum)) { 67 init(); 68 for(int i = 0; i < m; i++) { 69 scanf("%d%d%lld", &from, &to, &val); 70 add(from, to, val); 71 add(to, from, val); 72 } 73 s = 0, t = m+1; 74 spfa(); 75 printf("%lld\n", sum); 76 } 77 return 0; 78 }
dij
1 #include "iostream" 2 #include <string.h> 3 #include <queue> 4 using namespace std; 5 6 #define ll long long 7 const int maxn = 2020; 8 const ll INF = 1e18; 9 int n, snum, tnum; 10 int to[maxn], pre[maxn], p[maxn], a[maxn], index; 11 bool vis[maxn], mark[maxn]; 12 ll dis[maxn], w[maxn]; 13 14 struct Node { 15 int x; 16 ll y; 17 bool operator < (const Node &b) const { 18 return y > b.y; 19 } 20 }; 21 22 priority_queue<Node> pq; 23 24 void init() { 25 while(!pq.empty()) pq.pop(); 26 for(int i = 0; i < maxn; ++i) { 27 vis[i] = mark[i] = false, dis[i] = INF; 28 } 29 } 30 ll Dij() { 31 while(!pq.empty()) { 32 Node b = pq.top(); 33 pq.pop(); 34 int xx = b.x; 35 if(mark[xx]) return b.y; 36 if(vis[xx]) continue; 37 vis[xx] = true; 38 for(int i = p[xx]; i; i = pre[i]) { 39 int xxx = to[i]; 40 if(!vis[xxx] && dis[xxx] > dis[xx] + w[i]) { 41 dis[xxx] = dis[xx] + w[i]; 42 pq.push(Node {xxx, dis[xxx]}); 43 } 44 } 45 } 46 return INF; 47 } 48 49 void solve() { 50 init(); 51 int x; 52 for(int j = 0; j < snum; ++j) { 53 scanf("%d", &x); 54 dis[x] = 0; 55 pq.push(Node {x, 0}); 56 } 57 for(int i = 0; i < tnum; ++i){ 58 scanf("%d", &x); 59 mark[x] = true; 60 } 61 ll sum = Dij(); 62 printf("%lld\n", sum); 63 } 64 65 int main() { 66 #ifdef wenbao 67 freopen("in", "r", stdin); 68 #endif 69 while(~scanf("%d%d%d", &n, &snum, &tnum)) { 70 index = 1; 71 for(int i = 0; i < maxn; ++i) p[i] = 0; 72 int x, y; 73 ll z; 74 for(int i = 0; i < n; ++i) { 75 scanf("%d%d%lld", &x, &y, &z); 76 to[index] = y, w[index] = z, pre[index] = p[x], p[x] = index ++; 77 to[index] = x, w[index] = z, pre[index] = p[y], p[y] = index ++; 78 } 79 solve(); 80 } 81 return 0; 82 }
floyd
1 #include "iostream" 2 using namespace std; 3 4 #define INF 1e9 5 const int maxn = 1010; 6 int a[maxn][maxn], n, snum, tnum, x, y, z, b[maxn], c[maxn], sum, m; 7 8 void init() { 9 sum = INF, m = 0; 10 for(int i = 0; i < maxn; ++i) { 11 for(int j = 0; j < i; ++j) { 12 a[i][j] = a[j][i] = INF; 13 } 14 } 15 } 16 17 void floyd() { 18 int tt, s_kj, s_jk, a_ki, xx; 19 for (int k = 1; k <= m; k++) { 20 for (int i = 1; i <= m; i++) if (k != i) { 21 k < i ? a_ki = a[i][k], tt = k : a_ki = a[k][i], tt = i; 22 // skip if no path 23 if (a_ki == INF) continue; 24 for (int j = 1; j < tt; j++) { 25 s_kj = a_ki + a[k][j]; 26 if( s_kj < a[i][j] ) a[i][j] = s_kj; 27 } 28 for (int j = k + 1; j < i; j++) { 29 s_jk = a_ki + a[j][k]; 30 if( s_jk < a[i][j] ) a[i][j] = s_jk; 31 } 32 } 33 } 34 } 35 36 int main() { 37 #ifdef wenbao 38 freopen("in", "r", stdin); 39 #endif 40 while(~scanf("%d%d%d", &n, &snum, &tnum)) { 41 init(); 42 for(int i = 0; i < n; ++i) { 43 scanf("%d%d%d", &x, &y, &z); 44 if(z < a[x][y]) a[x][y] = a[y][x] = z; 45 if(x > m) m = x; 46 if(y > m) m = y; 47 } 48 floyd(); 49 for(int i = 0; i < snum; ++i) { 50 scanf("%d", &b[i]); 51 } 52 for(int i = 0; i < tnum; ++i) { 53 scanf("%d", &c[i]); 54 } 55 for(int i = 0; i < snum; ++i) { 56 for(int j = 0; j < tnum; ++j) { 57 if(b[i] > c[j]) { 58 if(a[b[i]][c[j]] < sum) sum = a[b[i]][c[j]]; 59 } else { 60 if(a[c[j]][b[i]] < sum) sum = a[c[j]][b[i]]; 61 } 62 } 63 } 64 printf("%d\n", sum); 65 } 66 return 0; 67 }
-----------------------------------------------------------
-------------------------------------------------------------
只有不断学习才能进步!
原文:https://www.cnblogs.com/wenbao/p/7453758.html