zoukankan      html  css  js  c++  java
  • BZOJ_1576_[Usaco2009 Jan]安全路经Travel&&BZOJ_3694_最短路_树链剖分+线段树

    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


    3694只是给出最短路树而已,这里考虑1576怎么做。

    首先求出最短路树。

    设第i个点到根的路径长度为dis[i]。

    考虑每条非树边<u,v>,有哪些牛牛可以经过这条边呢?

    设l=lca(u,v),只有u到l和l到v路径上的点对应的牛才能享受到这条边。

    考虑在子树内部的情况:最后一条边被割断因此走这条边不会减少到该点的距离。

    考虑在外面的情况:由于到祖先的边被割断根本走不到u或v。

    所以就变成了一个路径赋值取min,单点查询的问题。

    树剖+线段树即可。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <ext/pb_ds/priority_queue.hpp>
    using namespace std;
    using namespace __gnu_pbds;
    #define N 200050
    #define M 200050
    #define inf 0x3f3f3f3f
    #define ls p<<1
    #define rs p<<1|1
    vector<int>v[N];
    vector<int>w[N];
    int head[N],to[M<<1],nxt[M<<1],val[M<<1],cnt=1,n,m,xx[M],yy[M],zz[M],vis[M],use[M],t[N<<2],cov[N<<2],dis[N];
    int dep[N],fa[N],top[N],son[N],siz[N],idx[N],turn[M<<1],ww[M<<1];
    __gnu_pbds::priority_queue<pair<int,int> >q;
    struct shulianpoufen {
        int head[N],to[N<<1],nxt[N<<1],cnt;
         
    }T;
    inline void add(int u,int v,int w) {
        to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
    }
    void dij() {
        memset(dis,0x3f,sizeof(dis));
        dis[1]=0; q.push(make_pair(0,1));
        while(!q.empty()) {
            int x=q.top().second,i; q.pop();
            if(vis[x]) continue;
            vis[x]=1;
            for(i=head[x];i;i=nxt[i]) {
                if(dis[to[i]]+val[i]==dis[x]) {
                    // printf("%d %d
    ",x,to[i]);
                    v[x].push_back(to[i]); w[x].push_back(val[i]);
                    v[to[i]].push_back(x); w[to[i]].push_back(val[i]);
                    use[i>>1]=1;
                }
            }
            for(i=head[x];i;i=nxt[i]) {
                if(dis[to[i]]>dis[x]+val[i]) {
                    dis[to[i]]=dis[x]+val[i];
                    q.push(make_pair(-dis[to[i]],to[i]));
                }
            }
        }
    }
    void dfs1(int x,int y) {
        fa[x]=y; dep[x]=dep[y]+1; siz[x]=1;
        int i;
        for(i=head[x];i;i=nxt[i]) {
            if(to[i]!=y) {
                dis[to[i]]=dis[x]+val[i];
                dfs1(to[i],x);
                siz[x]+=siz[to[i]]; if(siz[to[i]]>siz[son[x]]) son[x]=to[i];
            }
        }
    }
    void dfs2(int x,int t) {
        int i; top[x]=t; idx[x]=++idx[0];
        if(son[x]) dfs2(son[x],t);
        for(i=head[x];i;i=nxt[i]) {
            if(to[i]!=fa[x]&&to[i]!=son[x]) dfs2(to[i],to[i]);
        }
    }
    void pushdown(int p) {
        if(cov[p]!=inf) {
            int d=cov[p];
            t[ls]=min(t[ls],d); t[rs]=min(t[rs],d);
            cov[ls]=min(cov[ls],d); cov[rs]=min(cov[rs],d);
            cov[p]=inf;
        }
    }
    void update(int l,int r,int x,int y,int v,int p) {
        if(x<=l&&y>=r) {
            t[p]=min(t[p],v); cov[p]=min(cov[p],v); return ;
        }
        pushdown(p);
        int mid=(l+r)>>1;
        if(x<=mid) update(l,mid,x,y,v,ls);
        if(y>mid) update(mid+1,r,x,y,v,rs);
        t[p]=min(t[ls],t[rs]);
    }
    int query(int l,int r,int x,int p) {
        if(l==r) return t[p];
        pushdown(p);
        int mid=(l+r)>>1;
        if(x<=mid) return query(l,mid,x,ls);
        else return query(mid+1,r,x,rs);
    }
    void solve() {
        dfs1(1,1); dfs2(1,0);
        memset(t,0x3f,sizeof(t));
        memset(cov,0x3f,sizeof(cov));
        int i;
        for(i=1;i<=m;i++) {
            if(!use[i]) {
                int x=xx[i],y=yy[i],z=zz[i]+dis[x]+dis[y];
                while(top[x]!=top[y]) {
                    if(dep[top[x]]>dep[top[y]]) swap(x,y);
                    update(1,n,idx[top[y]],idx[y],z,1);
                    y=fa[top[y]];
                }
                if(dep[x]<dep[y]) swap(x,y);
                if(x!=y) update(1,n,idx[y]+1,idx[x],z,1);
            }
        }
        for(i=2;i<=n;i++) {
            int tmp=query(1,n,idx[i],1);
            if(tmp==inf) puts("-1");
            else {
                printf("%d
    ",tmp-dis[i]);
            }
        }
    }
    int main() {
        scanf("%d%d",&n,&m);
        int i,j;
        for(i=1;i<=m;i++) {
            scanf("%d%d%d",&xx[i],&yy[i],&zz[i]);
            add(xx[i],yy[i],zz[i]); add(yy[i],xx[i],zz[i]);
        }
        dij();
        memset(head,0,sizeof(head)); cnt=0;
        for(i=1;i<=n;i++) {
            for(j=0;j<v[i].size();j++) add(v[i][j],i,w[i][j]);
        }
        solve();
    }
    
  • 相关阅读:
    一句SQL查询没门课程都低于80分的学生信息
    ★查询给定字符串中,出现最多的字符和出现的次数
    Eclipse自动加载源码----Attach Java Source
    Eclipse 修改workspace默认的字符集为 utf-8
    浅谈 Spring的AOP的实现 -- 动态代理
    浅谈高并发的理解
    为什么使用单例模式?
    正排索引 与 倒排索引
    图片裁剪
    微信小程序开发笔记
  • 原文地址:https://www.cnblogs.com/suika/p/9127156.html
Copyright © 2011-2022 走看看