最短路相关

题意:
给定数字n,m,(1≤n,m≤500000)
将n变为n*2的花费为2,将n变为n-3的花费为3,要求过程当中所有数字都在[1,500000]区间内。
求将n变为m的最少花费。

思路:
将每个数字视为图论中的点,数字之间的转换视为图论中的边。有向图!
500000个点,连边(i,i*2)权值为2,连边(i,i-3)权值为3
求n至m的最短路就是最小花费
除Floyd之外的方法,时间复杂度均符合要求

 1 #include<cstdio>
 2 #include<vector>
 3 #include<queue>
 4 using namespace std;
 5 
 6 const int inf = 99999999;
 7 const int maxn = 500000 + 5;
 8 struct edge {
 9     int v, w;
10 };
11 vector<vector<edge>>a;
12 vector<int>dis(maxn, inf);
13 vector<bool>flag(maxn, false);
14 
15 void add_edge(int u,int v,int w) {
16     edge tmp;
17     tmp.v = v;
18     tmp.w = w;
19     a[u].push_back(tmp);
20 }
21 
22 bool legal(int x) { return x > 0 && x <= 500000; }
23 
24 void spfa(int s) {
25     queue<int>q;
26     q.push(s);
27     dis[s] = 0;flag[s] = true;
28     while (!q.empty()) {
29         int u = q.front(); q.pop(); flag[u] = false;
30         for (int i = 0; i < a[u].size(); i++) {//扫描所有邻接点
31             if (dis[a[u][i].v] > dis[u] + a[u][i].w) {
32                 dis[a[u][i].v] = dis[u] + a[u][i].w;
33                 if (!flag[a[u][i].v]) {
34                     q.push(a[u][i].v);
35                     flag[a[u][i].v] = true;
36                 }
37             }
38         }
39     }
40 }
41 
42 int main() {
43     int s, t;
44     scanf("%d%d", &s, &t);
45     a.resize(maxn);
46     for (int i = 1; i <= maxn; i++) {
47         if (legal(i * 2)) add_edge(i, i * 2, 2);
48         if (legal(i - 3)) add_edge(i, i - 3, 3);
49     }
50     spfa(s);
51     if (dis[t] != inf)printf("%d
", dis[t]);
52     else printf("-1
");
53     return 0;
54 }

POJ3268

题意:N 个点,M 条有向边,求问从所有点到 X 的最短路加上从 X 到所有点的最短路加上总和的最大值

解法:这里要明白一件事情,就是点 a 到点 b 的最短路等于所有边反转后点 b 到点 a 的最短路。依据这个原理先算一遍从 X 到所有点的最短路,之后翻转所有边再算一遍即可。

网上说优化的Dijkstra会跑的比SPFA快,hhhh他们还是太年轻了。

 1 struct Edge {
 2     int from, to, w, next;
 3 };
 4 int head[MAXN], vis[MAXN];
 5 int dist[MAXN];
 6 int rev_head[MAXN];
 7 int rev_dist[MAXN];
 8 Edge e[100005], rev_e[100005];
 9 int N, M, tot, X, rev_tot;
10 
11 void add_edge(int i, int j, int w) {
12     e[tot].from = i, e[tot].to = j, e[tot].w = w;
13     e[tot].next = head[i];
14     head[i] = tot++;
15 }
16 
17 void add_rev_edge(int i, int j, int w) {
18     rev_e[rev_tot].from = i, rev_e[rev_tot].to = j, rev_e[rev_tot].w = w;
19     rev_e[rev_tot].next = rev_head[i];
20     rev_head[i] = rev_tot++;
21 }
22 
23 void SPFA(int s) {
24     queue<int> q;
25     for (int i = 1; i <= N; i++) dist[i] = INF;
26     memset(vis, false, sizeof(vis));
27     q.push(s);
28     dist[s] = 0;
29     while (!q.empty()) {
30         int u = q.front();
31         q.pop();
32         vis[u] = false;
33         for (int i = head[u]; i != -1; i = e[i].next) {
34             int v = e[i].to;
35             if (dist[v] > dist[u] + e[i].w) {
36                 dist[v] = dist[u] + e[i].w;
37                 if (!vis[v]) {
38                     vis[v] = true;
39                     q.push(v);
40                 }
41             }
42         }
43     }
44 }
45 
46 void rev_SPFA(int s) {
47     queue<int> q;
48     for (int i = 1; i <= N; i++) rev_dist[i] = INF;
49     memset(vis, 0, sizeof(vis));
50     q.push(s);
51     rev_dist[s] = 0;
52     while (!q.empty()) {
53         int u = q.front();
54         q.pop();
55         vis[u] = false;
56         for (int i = rev_head[u]; i != -1; i = rev_e[i].next) {
57             int v = rev_e[i].to;
58             if (rev_dist[v] > rev_dist[u] + rev_e[i].w) {
59                 rev_dist[v] = rev_dist[u] + rev_e[i].w;
60                 if (!vis[v]) {
61                     vis[v] = true;
62                     q.push(v);
63                 }
64             }
65         }
66     }
67 }
68 
69 int main() {
70 #ifndef ONLINE_JUDGE
71     freopen("input.txt", "r", stdin);
72 #endif
73     scanf("%d%d%d", &N, &M, &X);
74     tot = 0, rev_tot = 0;
75     memset(head, -1, sizeof(head));
76     memset(rev_head, -1, sizeof(rev_head));
77     int u, v, w;
78     for (int i = 1; i <= M; i++) {
79         scanf("%d%d%d", &u, &v, &w);
80         add_edge(u, v, w);
81         add_rev_edge(v, u, w);
82     }
83     SPFA(X);
84     rev_SPFA(X);
85     int ans = -1;
86     for (int i = 1; i <= N; i++) ans = max(ans, dist[i] + rev_dist[i]);
87     printf("%d
", ans);
88     return 0;
89 }
原文地址:https://www.cnblogs.com/romaLzhih/p/9489830.html