wenbao与多源多汇最短路

 

求多个起点多个终点的最短路,与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 }

 

 

 -----------------------------------------------------------

-------------------------------------------------------------

 

 

只有不断学习才能进步!

 

posted @ 2018-04-14 13:55  wenbao  阅读(400)  评论(0编辑  收藏  举报