zoukankan      html  css  js  c++  java
  • 1972: 最短路(shortest)

    题目描述

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

    题解

    did_i表示第ii个点到根的路径和
    一个点在不向上走一步的情况下,应该是在其子树内找到一个点,走到那然后通过一条非树边走出这棵子树,然后走到根更优
    即第ii个点的答案应为djdi+lenj,k+dkd_j-d_i+len_{j,k}+d_k
    jjii子树内,kkii子树外)
    考虑最小化dj+lenj,k+dkd_j+len_{j,k}+d_k,即每条非树边造成的影响
    对于一条非树边(j,k)(j,k),它所能影响到的点在j>lcaj->lca以及k>lcak->lca的路径上且不包括lcalca
    所以树剖,以树剖序建线段树,然后区间更新最小值即可
    效率O(nlog2n)O(nlog^2n)
    (有更好的方法,利用并查集,效率为O(nlogn)O(nlogn)

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define Ls k<<1
    #define Rs Ls|1
    #define F 0x3f3f3f3f
    #define I inline
    #define E register
    using namespace std;
    const int N=4005;struct O{int u,v,w;}p[100005];
    int n,m,c,t,head[N],V[N*2],nex[N*2],W[N*2],d[N],fa[N];
    int dep[N],top[N],sz[N],son[N],id[N],tt,a[N*4],dfn[N],s[N];
    I void add(E int u,E int v,E int w){
        V[++t]=v;nex[t]=head[u];head[u]=t;W[t]=w;
    }
    I void dfs1(E int x,E int fat,E int deep){
        fa[x]=fat;dep[x]=deep;sz[x]=1;
        for (E int i=head[x];i;i=nex[i]){
            if (V[i]==fat) continue;
            d[V[i]]=d[x]+W[i];
            dfs1(V[i],x,deep+1);
            sz[x]+=sz[V[i]];
            if (sz[V[i]]>sz[son[x]])
                son[x]=V[i];
        }
    }
    I void dfs2(E int x,E int tp){
        top[x]=tp;id[x]=++tt;dfn[tt]=x;
        if (son[x]) dfs2(son[x],tp);
        for (E int i=head[x];i;i=nex[i])
            if (V[i]^son[x] && V[i]^fa[x])
                dfs2(V[i],V[i]);
    }
    I void query(E int k,E int l,E int r,E int w){
        if (l==r){s[dfn[l]]=min(w,a[k]);return;}
        E int mid=l+r>>1;
        query(Ls,l,mid,min(a[k],w));
        query(Rs,mid+1,r,min(a[k],w));
    }
    I void update(E int k,E int l,E int r,E int L,E int R,E int w){
        if (L<=l && r<=R){a[k]=min(a[k],w);return;}
        E int mid=l+r>>1;
        if (mid>=L) update(Ls,l,mid,L,R,w);
        if (mid<R) update(Rs,mid+1,r,L,R,w);
    }
    I void update_chain(E int x,E int y,E int w){
        while(top[x]^top[y]){
            if (dep[top[x]]<dep[top[y]]) swap(x,y);
            update(1,1,n,id[top[x]],id[x],w);x=fa[top[x]];
        }
        if (dep[x]>dep[y]) swap(x,y);
        update(1,1,n,id[x]+1,id[y],w);
    }
    int main(){
        scanf("%d%d",&n,&m);memset(a,F,sizeof a);
        for (E int u,v,w,ty,i=1;i<=m;i++){
            scanf("%d%d%d%d",&u,&v,&w,&ty);
            if (ty) add(u,v,w),add(v,u,w);
            else p[++c]=(O){u,v,w};
        }
        dfs1(1,0,1);dfs2(1,1);
        for (E int i=1;i<=c;i++)
            update_chain(p[i].u,p[i].v,d[p[i].u]+d[p[i].v]+p[i].w);
        query(1,1,n,F);
        for (E int i=2;i<=n;i++)
            if (s[i]==F) puts("-1");
            else printf("%d ",s[i]-d[i]);
        return 0;
    }
    
  • 相关阅读:
    APP端自动化 之 Windows-Android-Appium环境搭建
    Python3学习笔记-继承、封装、多态
    Python3学习笔记-构造函数与析构函数
    多线程同时操作界面使用互斥体
    AX2009 C#客户端通过Web service批量审核工作流(一)
    AX2009报表发送邮件(二)
    AX2009报表发送邮件(一)
    AX2012分页显示数据
    AX2012 菜单根据不同公司动态显示
    AX2012使用域用户组
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/10544704.html
Copyright © 2011-2022 走看看