zoukankan      html  css  js  c++  java
  • BZOJ1576 [Usaco2009 Jan]安全路经Travel

    首先用Dijkstra做出最短路生成树,设dis[p]为1到p点的最短路长度

    对于一条不在生成树上的边u -> v,不妨设fa为u、v的lca

    则一fa到v的路径上的任意点x都可以由u达到,走的方式是1 -> fa -> u -> v -> x,dis'[x] = dis[u] + dis(u, v) + dis[v] - dis[x]

    于是可以用dis[u] + dis(u, v) + dis[v]更新fa到v的路径上的所有点

    链剖一下,线段树lazytag就好了,连pushdown都不需要

      1 /**************************************************************
      2     Problem: 1576
      3     User: rausen
      4     Language: C++
      5     Result: Accepted
      6     Time:2276 ms
      7     Memory:16636 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <algorithm>
     12 #include <queue>
     13  
     14 using namespace std;
     15 const int N = 1e5 + 5;
     16 const int M = 2e5 + 5;
     17 const int inf = 1e9;
     18  
     19 struct edge {
     20     int next, to, v, vis;
     21     edge(int _n = 0, int _t = 0, int _v = 0, int __v = 0) : next(_n), to(_t), v(_v), vis(__v) {}
     22 } e[M << 1];
     23  
     24 struct heap_node {
     25     int v, e, to;
     26     heap_node(int _v = 0, int _e = 0, int _t = 0) : v(_v), e(_e), to(_t) {}
     27      
     28     inline bool operator < (const heap_node &p) const {
     29         return v > p.v;
     30     }
     31 };
     32  
     33 struct tree_node {
     34     int fa, sz, dep;
     35     int top, son, e;
     36     int w;
     37 } tr[N];
     38  
     39 struct seg_node {
     40     seg_node *ls, *rs;
     41     int mn;
     42 } *seg_root, *seg_null, mempool[N << 2], *cnt_seg = mempool;
     43  
     44 int n, m, cnt_q;
     45 int first[N], tot = 1;
     46 int dis[N];
     47 priority_queue <heap_node> h;
     48  
     49 inline int read() {
     50     static int x;
     51     static char ch;
     52     x = 0, ch = getchar();
     53     while (ch < '0' || '9' < ch)
     54         ch = getchar();
     55     while ('0' <= ch && ch <= '9') {
     56         x = x * 10 + ch - '0';
     57         ch = getchar();
     58     }
     59     return x;
     60 }
     61  
     62 inline void Add_Edges(int x, int y, int v) {
     63     e[++tot] = edge(first[x], y, v), first[x] = tot;
     64     e[++tot] = edge(first[y], x, v), first[y] = tot;
     65 }
     66  
     67 inline void add_to_heap(int p) {
     68     static int x;
     69     for (x = first[p]; x; x = e[x].next)
     70         if (dis[e[x].to] == inf)
     71             h.push(heap_node(e[x].v + dis[p], x, e[x].to));
     72 }
     73  
     74 void Dijkstra(int S) {
     75     int p;
     76     for (p = 1; p <= n; ++p) dis[p] = inf;
     77     while (!h.empty()) h.pop();
     78     dis[S] = 0, add_to_heap(S);
     79     while (!h.empty()) {
     80         if (dis[h.top().to] != inf) {
     81             h.pop();
     82             continue;
     83         }
     84         p = h.top().to;
     85         dis[p] = h.top().v, e[tr[p].e = h.top().e].vis = 1;
     86         h.pop(), add_to_heap(p);
     87     }
     88 }
     89  
     90 #define y e[x].to
     91 #define Son tr[p].son
     92 void dfs(int p) {
     93     int x;
     94     tr[p].sz = 1;
     95     for (x = first[p]; x; x = e[x].next)
     96         if (tr[y].e == x) {
     97             tr[y].dep = tr[p].dep + 1;
     98             dfs(y);
     99             tr[p].sz += tr[y].sz;
    100             if (Son == 0 || tr[y].sz > tr[Son].sz) Son = y;
    101         }
    102 }
    103  
    104 void DFS(int p) {
    105     int x;
    106     tr[p].w = ++cnt_q;
    107     if (Son)
    108         tr[Son].top = tr[p].top, DFS(Son);
    109         for (x = first[p]; x; x = e[x].next)
    110             if (y != Son && tr[y].e == x)
    111                 tr[y].top = y, DFS(y);
    112 }
    113 #undef y
    114 #undef Son
    115  
    116 #define mid (l + r >> 1)
    117 #define Ls p -> ls
    118 #define Rs p -> rs
    119 #define Mn p -> mn
    120 inline void seg_make_null(seg_node *&p) {
    121     p = cnt_seg, Ls = Rs = p, Mn = inf;
    122 }
    123  
    124 inline void seg_new(seg_node *&p) {
    125     p = ++cnt_seg, *p = *seg_null;
    126 }
    127  
    128 void seg_build(seg_node *&p, int l, int r) {
    129     seg_new(p);
    130     if (l == r) return;
    131     seg_build(Ls, l, mid), seg_build(Rs, mid + 1, r);
    132 }
    133  
    134 void seg_modify(seg_node *p, int l, int r, int L, int R, int v) {
    135     if (L <= l && r <= R) {
    136         Mn = min(Mn, v);
    137         return;
    138     }
    139     if (L <= mid) seg_modify(Ls, l, mid, L, R, v);
    140     if (mid + 1 <= R) seg_modify(Rs, mid + 1, r, L, R, v);
    141 }
    142  
    143 int seg_query(seg_node *p, int l, int r, int pos) {
    144     if (l == r) return Mn;
    145     return min(Mn, pos <= mid ? seg_query(Ls, l, mid, pos) : seg_query(Rs, mid + 1, r, pos));
    146 }
    147 #undef mid
    148 #undef Ls
    149 #undef Rs
    150 #undef Mn
    151  
    152 int get_lca(int x, int y) {
    153     while (tr[x].top != tr[y].top) {
    154         if (tr[tr[x].top].dep < tr[tr[y].top].dep) swap(x, y);
    155         x = tr[tr[x].top].fa;
    156     }
    157     if (tr[x].dep < tr[y].dep) swap(x, y);
    158     return y;
    159 }
    160  
    161 void work_modify(int x, int fa, int v) {
    162     while (tr[x].top != tr[fa].top) {
    163         seg_modify(seg_root, 1, n, tr[tr[x].top].w, tr[x].w, v);
    164         x = tr[tr[x].top].fa;
    165     }
    166     seg_modify(seg_root, 1, n, tr[fa].w + 1, tr[x].w, v);
    167 }
    168  
    169 int main() {
    170     int i, x, y, z, fa, tmp;
    171     n = read(), m = read();
    172     for (i = 1; i <= m; ++i) {
    173         x = read(), y = read(), z = read();
    174         Add_Edges(x, y, z);
    175     }
    176     Dijkstra(1);
    177     for (i = 2; i <= n; ++i)
    178         tr[i].fa = e[tr[i].e ^ 1].to;
    179     dfs(1);
    180     tr[1].top = 1, DFS(1);
    181     seg_make_null(seg_null);
    182     seg_build(seg_root, 1, n);
    183 #define y e[x].to
    184     for (i = 1; i <= n; ++i)
    185         for (x = first[i]; x; x = e[x].next) 
    186             if (!e[x].vis) work_modify(y, get_lca(i, y), dis[i] + dis[y] + e[x].v);
    187 #undef y
    188     for (i = 2; i <= n; ++i) {
    189         tmp = seg_query(seg_root, 1, n, tr[i].w);
    190         printf("%d
    ", tmp == inf ? -1 : tmp - dis[i]);
    191     }
    192     return 0;
    193 }
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    java:数组操作工具类 java.util.Arrays包 主要方法详解
    java:接口特性 接口与抽象类/普通类的区别
    mybatis教程:入门>>精通>>实战
    Java :内部类基础详解
    Java swing: 实现ActionListener监听器的三种途径
    Java:final、static关键字 详解+两者结合使用
    Java:双括号初始化 /匿名内部类初始化法
    Java:静态内部类的使用目的、使用限制、与非静态内部类的对比
    域名解析>>"记录类型" 说明
    Java:接口继承接口 (多继承机制)
  • 原文地址:https://www.cnblogs.com/rausen/p/4436273.html
Copyright © 2011-2022 走看看