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

    1576: [Usaco2009 Jan]安全路经Travel

    Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 1448  Solved: 512 [Submit][Status][Discuss]

    Description

    Input

    * 第一行: 两个空格分开的数, N和M

    * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i

    Output

    * 第1..N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最短路经上最后一条牛路的最少的时间.如果这样的路经不存在,输出-1.

    Sample Input

    4 5
    1 2 2
    1 3 2
    3 4 4
    3 2 1
    2 4 3

    输入解释:

    跟题中例子相同

    Sample Output

    3
    3
    6

    输出解释:

    跟题中例子相同
     
    题目限制没有重边自环,且到每个点的最短路只有一条。。
    dijkstra预处理(这题卡SPFA),建最短路树
    对于一条无向边$(u, v)$,其长度为$w$
    若其不在树上,那么考虑这条边的影响:对于$lca$到$v$的路径上所有点$t$都可以走$1,lca,u,v,t$
    路径长度显然为$dis[u]+dis[v]+w-d[x]$
    只要维护$dis[u]+dis[v]+w$最小值,树剖+线段树即可
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std; 
    char buf[10000000], *ptr = buf - 1;
    inline int readint(){
        int n = 0;
        char ch = *++ptr;
        while(ch < '0' || ch > '9') ch = *++ptr;
        while(ch <= '9' && ch >= '0'){
            n = (n << 1) + (n << 3) + ch - '0';
            ch = *++ptr;
        }
        return n;
    }
    const int maxn = 100000 + 10, maxm = 200000 + 10, INF = 0x3f3f3f3f;
    int n, m;
    struct Edge{
        int to, val, next;
        Edge(){}
        Edge(int _t, int _v, int _n): to(_t), val(_v), next(_n){}
    }e[maxm * 2];
    int fir[maxn] = {0}, cnt = 0;
    inline void ins(int u, int v, int w){
        e[++cnt] = Edge(v, w, fir[u]); fir[u] = cnt;
        e[++cnt] = Edge(u, w, fir[v]); fir[v] = cnt;
    }
    struct Node{
        int id, dis;
        Node(){}
        Node(int _i, int _d): id(_i), dis(_d){}
    }tmp;
    class cmp{
        public:
            bool operator () (const Node &a, const Node &b){
                return a.dis > b.dis;
            }
    };
    priority_queue<Node, vector<Node>, cmp> q;
    int dis[maxn], pre[maxn];
    bool vis[maxn], mark[maxm * 2];
    void dijkstra(){
        for(int i = 1; i <= n; i++){
            dis[i] = 0x3f3f3f3f;
            vis[i] = false;
        }
        dis[1] = 0;
        q.push(Node(1, 0));
        int u, v;
        while(!q.empty()){
            tmp = q.top(); q.pop();
            u = tmp.id;
            if(vis[u]) continue;
            vis[u] = true;
            for(int i = fir[u]; i; i = e[i].next){
                v = e[i].to;
                if(dis[v] > tmp.dis + e[i].val){
                    mark[pre[v]] = false;
                    mark[i] = true;
                    pre[v] = i;
                    dis[v] = tmp.dis + e[i].val;
                    q.push(Node(v, dis[v]));
                }
            }
        }
    }
    int fa[maxn], son[maxn], siz[maxn], dep[maxn];
    void dfs1(int u){
        son[u] = 0;
        siz[u] = 1;
        for(int v, i = fir[u]; i; i = e[i].next){
            if(!mark[i]) continue;
            v = e[i].to;
            fa[v] = u;
            dep[v] = dep[u] + 1;
            dfs1(v);
            siz[u] += siz[v];
            if(!son[u] || siz[v] > siz[son[u]]) son[u] = v;
        }
    }
    int top[maxn], ref[maxn], tcnt = 0;
    void dfs2(int u){
        ref[u] = ++tcnt;
        if(!son[u]) return;
        top[son[u]] = top[u];
        dfs2(son[u]);
        for(int v, i = fir[u]; i; i = e[i].next){
            if(!mark[i]) continue;
            v = e[i].to;
            if(v == son[u]) continue;
            top[v] = v;
            dfs2(v);
        }
    }
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    int Min[maxn << 2], tag[maxn << 2];
    void Build(int l, int r, int rt){
        Min[rt] = tag[rt] = INF;
        if(l == r) return;
        else{
            int mid = l + r >> 1;
            Build(lson);
            Build(rson);
        }
    }
    inline void PushDown(int rt){
        if(tag[rt] == INF) return;
        Min[rt << 1] = min(Min[rt << 1], tag[rt]);
        Min[rt << 1 | 1] = min(Min[rt << 1 | 1], tag[rt]);
        tag[rt << 1] = min(tag[rt << 1], tag[rt]);
        tag[rt << 1 | 1] = min(tag[rt << 1 | 1], tag[rt]);
        tag[rt] = INF;
    }
    void Update(int ql, int qr, int val, int l, int r, int rt){
        Min[rt] = min(Min[rt], val);
        if(ql <= l && r <= qr) tag[rt] = min(tag[rt], val);
        else{
            PushDown(rt);
            int mid = l + r >> 1;
            if(ql <= mid) Update(ql, qr, val, lson);
            if(qr > mid) Update(ql, qr, val, rson);
        }
    }
    int Query(int qw, int l, int r, int rt){
        if(l == r) return Min[rt];
        else{
            PushDown(rt);
            int mid = l + r >> 1;
            if(qw <= mid) return Query(qw, lson);
            else return Query(qw, rson);
        }
    }
    inline int Lca(int x, int y){
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        return x;
    }
    inline void Change(int x, int f, int val){
        while(top[x] != top[f]){
            Update(ref[top[x]], ref[x], val, 1, n, 1);
            x = fa[top[x]];
        }
        if(x != f) Update(ref[f] + 1, ref[x], val, 1, n, 1);
    }
    int a[maxm], b[maxm], t[maxm];
    int main(){
        fread(buf, sizeof(char), sizeof(buf), stdin);
        n = readint();
        m = readint();
        for(int i = 1; i <= m; i++){
            a[i] = readint();
            b[i] = readint();
            t[i] = readint();
            ins(a[i], b[i], t[i]);
        }
        dijkstra();
        dfs1(1);
        dfs2(1);
        Build(1, n, 1);
        for(int lca, i = 1; i <= m; i++){
            lca = Lca(a[i], b[i]);
            if(!mark[i * 2 - 1]) Change(b[i], lca, dis[a[i]] + dis[b[i]] + t[i]);
            if(!mark[i * 2]) Change(a[i], lca, dis[a[i]] + dis[b[i]] + t[i]);
        }
        for(int t, i = 2; i <= n; i++){
            t = Query(ref[i], 1, n, 1);
            if(t != INF) printf("%d
    ", t - dis[i]);
            else puts("-1");
        }
        return 0;
    };
  • 相关阅读:
    安装MSSQL2008出现的问题记录
    制作安装包遇到的问题
    算法设计方法动态规划
    基础果然要牢记(一次失败的电面)
    搜狗垂搜笔试
    几种堆的时间复杂度分析
    正则表达式转NFA
    组合数学(1)
    算法设计方法贪心算法
    最短路径问题
  • 原文地址:https://www.cnblogs.com/ruoruoruo/p/7517604.html
Copyright © 2011-2022 走看看