zoukankan      html  css  js  c++  java
  • 最短路相关

    题意:
    给定数字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 }
  • 相关阅读:
    事务
    一、python 基础之基础语法
    二、python 中五种常用的数据类型
    三、python函数详解
    四、 面向对象(一)
    五、面向对象(二)——继承与重写
    六、异常处理、日志打印、文件操作
    scrapy(一):基础用法
    # scrapy(二):get请求
    scrapy(三):post请求
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/9489830.html
Copyright © 2011-2022 走看看