[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\n", t - dis[i]);
        else puts("-1");
    }
    return 0;
};

 

posted @ 2017-09-13 20:46  jzyy  阅读(134)  评论(0编辑  收藏  举报