zoukankan      html  css  js  c++  java
  • BZOJ 3694 最短路

    3694: 最短路

    Time Limit: 5 Sec  Memory Limit: 256 MB
    Submit: 303  Solved: 153
    [Submit][Status][Discuss]

    Description

    给出一个n个点m条边的无向图,n个点的编号从1~n,定义源点为1。定义最短路树如下:从源点1经过边集T到任意一点i有且仅有一条路径,且这条路径是整个图1到i的最短路径,边集T构成最短路树。 给出最短路树,求对于除了源点1外的每个点i,求最短路,要求不经过给出的最短路树上的1到i的路径的最后一条边。
     

    Input

    第一行包含两个数n和m,表示图中有n个点和m条边。
    接下来m行,每行有四个数ai,bi,li,ti,表示图中第i条边连接ai和bi权值为li,ti为1表示这条边是最短路树上的边,ti为0表示不是最短路树上的边。

    Output

    输出n-1个数,第i个数表示从1到i+1的要求的最短路。无法到达输出-1。

    Sample Input

    5 9
    3 1 3 1
    1 4 2 1
    2 1 6 0
    2 3 4 0
    5 2 3 0
    3 2 2 1
    5 3 1 1
    3 5 2 0
    4 5 4 0

    Sample Output

    6 7 8 5

    HINT

     对于100%的数据,n≤4000,m≤100000,1≤li≤100000

    Source

    我的做法是树链剖分+线段树

    对于一条不在最短路树的有向边(无向可看成两条有向)u-v,长度L,设t=lca(u,v)

    那么对于t-v的路径上所有点x,都可通过1-t-u-v-x

    路径长度为d[u]+L+d[v]-d[x]

    最小化这个长度,也就是最小化d[u]+d[v]+L

    所以我们可以用这个值去更新t-v所有点(不包括t)的最短路长度

    这一步可以用线段树操作。。。

    /**************************************************************
        Problem: 3694
        User: zhangenming
        Language: C++
        Result: Accepted
        Time:572 ms
        Memory:5952 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    #define ll long long
    #define inf 1e9+10
    using namespace std;
    inline int read(){
        int x=0;int f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int MAXN=1e4+10;
    struct node{
        int y,next,v;
    }e[MAXN];
    int linkk[MAXN],len,dis[MAXN],n,m,u[200010],v[200010],l[200010],is[200010],f[MAXN][25],dep[MAXN],son[MAXN],siz[MAXN],dfn[MAXN],dfs_clock,top[MAXN],ans,val,x,y;
    struct sig{
        int minn;
    }T[MAXN<<2];
    inline void insertt(int x,int y,int v){
        e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;e[len].v=v;
    }
    inline void dfs1(int x,int fa){
        dep[x]=dep[fa]+1;f[x][0]=fa;siz[x]=1;
        for(int i=linkk[x];i;i=e[i].next){
            if(e[i].y!=fa){
                dis[e[i].y]=dis[x]+e[i].v;dfs1(e[i].y,x);siz[x]+=siz[e[i].y];
                if(!son[x]) son[x]=e[i].y;
                else if(siz[e[i].y]>siz[son[x]]) son[x]=e[i].y;
            }
        }
    }
    inline void dfs2(int x,int fa){
        dfn[x]=++dfs_clock;top[x]=fa;
        if(son[x]) dfs2(son[x],fa);
        for(int i=linkk[x];i;i=e[i].next){
            if(!dfn[e[i].y]&&e[i].y!=fa){
                dfs2(e[i].y,e[i].y);
            }
        }
    }
    inline void getanser(){
        for(int i=1;i<=20;i++){
            for(int j=1;j<=n;j++){
                f[j][i]=f[f[j][i-1]][i-1];
            }
        }
    }
    inline int lca(int x,int y){
        if(x==y) return x;
        if(dep[x]<dep[y]) swap(x,y);
        for(int i=20;i>=0;i--){
            if(dep[x]-(1<<i)>=dep[y]) x=f[x][i];
        }
        if(x==y) return x; 
        for(int i=20;i>=0;i--){
            if(f[x][i]!=f[y][i]&&f[x][i]!=0){
                x=f[x][i];y=f[y][i];
            }
        }
        return f[x][0];
    }
    inline void build(int l,int r,int rt){
        T[rt].minn=inf;
        if(l==r) return;
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1); 
    }
    inline void insert(int l,int r,int rt){
        if(l>y||r<x) return;
        if(l>=x&&r<=y){
            T[rt].minn=min(T[rt].minn,val);
            return ;
        }
        int mid=(l+r)>>1;
        insert(l,mid,rt<<1);
        insert(mid+1,r,rt<<1|1);
    }
    inline void change(int u,int v,int vl){
        int t=lca(u,v);
        val=dis[u]+vl+dis[v];
        while(top[u]!=top[t]){
            x=dfn[top[u]];y=dfn[u];
            insert(1,n,1);u=f[top[u]][0];
        }
        if(u!=t) x=dfn[t]+1,y=dfn[u],insert(1,n,1);
        while(top[v]!=top[t]){
            x=dfn[top[v]],y=dfn[v];
            insert(1,n,1);v=f[top[v]][0];
        }
        if(v!=t) x=dfn[t]+1,y=dfn[v],insert(1,n,1); 
    }
    inline void query(int l,int r,int rt){
        ans=min(ans,T[rt].minn);
        if(l==r) return;
        int mid=(l+r)>>1;
        if(x<=mid) query(l,mid,rt<<1);
        else query(mid+1,r,rt<<1|1);
    }
    int main(){
        //freopen("All.in","r",stdin);
        //freoepn("All.out","w",stdout);
        n=read();m=read();
        for(int i=1;i<=m;i++){
            u[i]=read();v[i]=read();l[i]=read();is[i]=read();
            if(is[i]) insertt(u[i],v[i],l[i]),insertt(v[i],u[i],l[i]);
        }
        dfs1(1,0);dfs2(1,0);
        getanser();
        build(1,n,1);
        for(int i=1;i<=m;i++){
            if(!is[i]) change(u[i],v[i],l[i]);
        }
        for(int i=2;i<n;i++){
            //cout<<dfn[i]<<endl;
            x=dfn[i];ans=inf;query(1,n,1);
            if(ans==inf) printf("-1 ");
            else printf("%d ",ans-dis[i]);
        }
        if(n!=1){
            x=dfn[n];ans=inf;query(1,n,1);
            if(ans==inf) printf("-1");
            else printf("%d",ans-dis[n]);
        }
        return 0;
    }
    

      

  • 相关阅读:
    mangodb学习0.1 概念
    express 学习笔记(一)路由
    vue配置路由
    screenX, clientX, pageX
    svg的世界、视窗、视野
    window.print()打印网页(一)
    cookie基础
    BOM基础
    Java三大特征:封装 继承 多态
    面向对象
  • 原文地址:https://www.cnblogs.com/something-for-nothing/p/9349863.html
Copyright © 2011-2022 走看看