• bzoj 4289 Tax


    题目传送门

      这是一条通往vjudge的神秘通道

      这是一条通往bzoj的神秘通道

    题目大意

      如果一条路径走过的边依次为$e_{1}, e_{2}, cdots , e_{k}$,那么它的长度为$e_{1} + max (e_{1}, e_{2}) + max (e_{2}, e_{3}) + cdots + max (e_{k - 1}, e_{k}) + e_{k}$,问点$1$到点$n$的最短路。

      显然需要把状态记在最后一条边上。

      然后给一个菊花图,这个做法就gg了。

      因此考虑一些黑科技。

      可以把边看成点,然后考虑如何在辺与边之间快速连边。

      对于一个点的出边,可以把它们按照权值排序,大的向比它略小的连一条权值为0的边,小的向比它略大的连一天权值为它们边权之差的边。

      然后原图中每条边向它的反向边连一条边权相同的边。

      然后再建两个虚点,一个起点,向以1为起点的边连边,边权不变。一个终点,以$n$为终点的边向它连边。

    Code

      1 /**
      2  * bzoj
      3  * Problem#4289
      4  * Accepted
      5  * Time: 3200ms
      6  * Memory: 31292k
      7  */
      8 #include <bits/stdc++.h>
      9 #ifndef WIN32
     10 #define Auto "%lld"
     11 #else
     12 #define Auto "%I64d"
     13 #endif
     14 using namespace std;
     15 typedef bool boolean;
     16 
     17 #define ll long long
     18 
     19 typedef class Edge {
     20     public:
     21         int end, next, w;
     22         
     23         Edge(int end = 9, int next = 0, int w = 0):end(end), next(next), w(w) {        }
     24 }Edge;
     25 
     26 typedef class MapManager {
     27     public:
     28         int ce;
     29         int *h;
     30         Edge *es;
     31         
     32         MapManager() {        }
     33         MapManager(int n, int m):ce(-1) {
     34             h = new int[(n + 1)];
     35             es = new Edge[(m + 5)];
     36             memset(h, -1, sizeof(int) * (n + 1));
     37         }
     38         
     39         void addEdge(int u, int v, int w) {
     40             es[++ce] = Edge(v, h[u], w);
     41             h[u] = ce;
     42 //            cerr << u << "->" << v << " " << w << endl;
     43         }
     44         
     45         Edge& operator [] (int pos) const {
     46             return es[pos];
     47         }
     48 }MapManager;
     49 
     50 int n, m;
     51 Edge *es;
     52 vector<int> *dg;
     53 MapManager g;
     54 
     55 inline void init() {
     56     scanf("%d%d", &n, &m);
     57     es = new Edge[(m + 1)];
     58     dg = new vector<int>[(n + 1)];
     59     for (int i = 0; i < m; i++) {
     60         scanf("%d%d%d", &es[i].end, &es[i].next, &es[i].w);
     61         dg[es[i].end].push_back(i << 1);
     62         dg[es[i].next].push_back(i << 1 | 1);
     63     }
     64 }
     65 
     66 boolean cmp(const int& a, const int& b) {
     67     return es[a >> 1].w < es[b >> 1].w;
     68 }
     69 
     70 int s, t;
     71 
     72 inline void build() {
     73     g = MapManager((m << 1) + 2, m << 3);
     74     s = m << 1, t = m << 1 | 1;
     75     for (int i = 1; i <= n; i++) {
     76         sort(dg[i].begin(), dg[i].end(), cmp);
     77         for (int j = 1; j < (signed) dg[i].size(); j++) {
     78             int u = (j) ? (dg[i][j - 1]) : (-1), v = dg[i][j];
     79             g.addEdge(v, u, 0);
     80             g.addEdge(u, v, es[v >> 1].w - es[u >> 1].w);
     81         }
     82     }
     83     
     84     for (int i = 0; i < (signed) dg[1].size(); i++)
     85         g.addEdge(s, dg[1][i], es[dg[1][i] >> 1].w);
     86     for (int i = 0; i < (signed) dg[n].size(); i++)
     87         g.addEdge(dg[n][i] ^ 1, t, es[dg[n][i] >> 1].w);
     88     
     89     for (int i = 0, w; i < m; i++) {
     90         w = es[i].w;
     91         g.addEdge(i << 1, i << 1 | 1, w);
     92         g.addEdge(i << 1 | 1, i << 1, w);
     93     }
     94 }
     95 
     96 typedef class Node {
     97     public:
     98         int p;
     99         ll dis;
    100         
    101         Node(int p = 0, ll dis = 0):p(p), dis(dis) {            }
    102         
    103         boolean operator < (Node b) const {
    104             return dis > b.dis;
    105         }
    106 }Node;
    107 
    108 ll *f;
    109 priority_queue<Node> que;
    110 inline ll dijstra() {
    111     f = new ll[(m << 1) + 2];
    112     memset(f, 0x3f, sizeof(ll) * ((m << 1) + 2));
    113     que.push(Node(s, f[s] = 0));
    114     while (!que.empty()) {
    115         Node e = que.top();
    116         que.pop();
    117         if (e.dis != f[e.p])    continue;
    118         for (int i = g.h[e.p]; ~i; i = g[i].next) {
    119             Node eu (g[i].end, e.dis + g[i].w);
    120             if (eu.dis < f[eu.p]) {
    121                 f[eu.p] = eu.dis;
    122                 que.push(eu);
    123             }
    124         }
    125     }
    126     return f[t];
    127 }
    128 
    129 inline void solve() {
    130     printf(Auto"
    ", dijstra());
    131 }
    132 
    133 int main() {
    134     init();
    135     build();
    136     solve();
    137     return 0;
    138 }
  • 相关阅读:
    LeetCode188 买卖股票的最佳时机 IV(dp)
    LeetCode123 买卖股票的最佳时机 III(贪心)
    LeetCode69 x的平方根 (二分)
    Java SE 17 新增特性
    Java SE 15 新增特性
    使用位运算技巧实现加减乘除
    前缀树的设计与实现
    使用二分法来解决的一些问题
    Java SE 16 新增特性
    位图的使用与实现
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8504265.html
Copyright © 2020-2023  润新知