zoukankan      html  css  js  c++  java
  • HDU 1535 Invitation Cards (最短路,附SLF优化SPFA)

    题目:

    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模板

    代码:加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 }
    HDU 1535
  • 相关阅读:
    反射
    jQuery之Dom操作
    Jquery学习开篇
    c#构造函数
    c#之委托
    DataX启动步骤解析
    JobContainer
    DataX 启动配置
    DataX源码分析(2)
    DataX源码分析(1)
  • 原文地址:https://www.cnblogs.com/xysmlx/p/3949948.html
Copyright © 2011-2022 走看看