BZOJ 1576: [Usaco2009 Jan]安全路经Travel【最短路树】【树链剖分】

来源:互联网 发布:阴阳师录屏软件 编辑:程序博客网 时间:2024/05/20 13:05

Description

这里写图片描述

题解

复习一下树链剖分。

最短路树,非树边与树边形成的环上,除了LCA,其他的点都可以经过非树边,从所有答案中刷最小值,用树链剖分维护。

代码

#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#define maxn 100006#define maxe 200006using namespace std;inline char nc(){    static char buf[100000],*i=buf,*j=buf;    return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;}inline int _read(){    char ch=nc();int sum=0;    while(!(ch>='0'&&ch<='9'))ch=nc();    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();    return sum;}int n,e,N,tem,tot[2],dep[maxn],id[maxn],dis[maxn],fa[maxn],top[maxn],num[maxn],H_son[maxn],    lnk[2][maxn],son[2][maxe*2],nxt[2][maxe*2],w[2][maxe*2];bool vis[maxn];struct point{    int x,s;    bool operator <(const point&b)const{return s>b.s;}};priority_queue <point > heap;struct side{    int x,y,w;}a[maxe];struct data{    int l,r,tag,x;    void add(int k){        tag=min(tag,k);x=min(x,k);    }}tree[maxn*4];void add(int p,int x,int y,int z){    nxt[p][++tot[p]]=lnk[p][x];son[p][tot[p]]=y;w[p][tot[p]]=z;lnk[p][x]=tot[p];}void dij(){    memset(vis,1,sizeof(vis));memset(dis,63,sizeof(dis));    dis[1]=0;point p;p.x=1;p.s=0;heap.push(p);    for(int i=1;i<=n;i++){        while(!vis[heap.top().x])heap.pop();        p=heap.top();heap.pop();        vis[p.x]=0;        for(int j=lnk[0][p.x];j;j=nxt[0][j]) if(vis[son[0][j]]&&dis[p.x]+w[0][j]<dis[son[0][j]]){            dis[son[0][j]]=dis[p.x]+w[0][j];fa[son[0][j]]=p.x;            point pp;pp.x=son[0][j];pp.s=dis[son[0][j]];heap.push(pp);        }    }    for(int i=2;i<=n;i++)add(1,fa[i],i,0);}void dfs1(int x){    vis[x]=0;num[x]=1;    for(int j=lnk[1][x];j;j=nxt[1][j]) if(vis[son[1][j]]){        dep[son[1][j]]=dep[x]+1;        dfs1(son[1][j]);        if(num[son[1][j]]>num[H_son[x]])H_son[x]=son[1][j];        num[x]+=num[son[1][j]];    }}void build(int p,int l,int r){    tree[p].l=l;tree[p].r=r;tree[p].tag=tree[p].x=1e9;    if(l>=r)return;    int mid=(l+r)>>1;    build(p<<1,l,mid);build(p<<1|1,mid+1,r);}void pushdown(int p){    if(tree[p].tag==1e9)return;    tree[p<<1].add(tree[p].tag);tree[p<<1|1].add(tree[p].tag);    tree[p].tag=1e9;}void update(int p,int l,int r,int k){    if(tree[p].l>r||tree[p].r<l)return;    if(l<=tree[p].l&&r>=tree[p].r){        tree[p].add(k);return;    }    pushdown(p);    update(p<<1,l,r,k);update(p<<1|1,l,r,k);    tree[p].x=min(tree[p<<1].x,tree[p<<1|1].x);}int query(int p,int k){    if(tree[p].l>k||tree[p].r<k)return 1e9;    if(tree[p].l==tree[p].r)return tree[p].x;    pushdown(p);    return min(query(p<<1,k),query(p<<1|1,k));}void dfs2(int x,int y){    vis[x]=0;id[x]=++tem;top[x]=y;    if(H_son[x]){        fa[H_son[x]]=x;        dfs2(H_son[x],y);    }    for(int j=lnk[1][x];j;j=nxt[1][j])if(vis[son[1][j]]){        fa[son[1][j]]=x;        dfs2(son[1][j],son[1][j]);    }}void change(int x,int y,int k){    while(top[x]!=top[y]){        if(dep[top[x]]<dep[top[y]])swap(x,y);        update(1,id[top[x]],id[x],k);        x=fa[top[x]];    }    if(x==y)return;    if(dep[x]>dep[y])swap(x,y);    update(1,id[H_son[x]],id[y],k);}int main(){    freopen("travel.in","r",stdin);    freopen("travel.out","w",stdout);    n=_read();e=_read();    for(int i=1,x,y,z;i<=e;i++)x=_read(),y=_read(),z=_read(),add(0,x,y,z),add(0,y,x,z);    dij();    for(int i=1;i<=n;i++)     for(int j=lnk[0][i];j;j=nxt[0][j]) if((j&1)&&fa[i]!=son[0][j]&&fa[son[0][j]]!=i){        ++N;a[N].x=i;a[N].y=son[0][j];a[N].w=w[0][j]+dis[a[N].x]+dis[a[N].y];     }    memset(vis,1,sizeof(vis));dep[1]=1;    dfs1(1);    memset(vis,1,sizeof(vis));    build(1,1,n);dfs2(1,1);    for(int i=1;i<=N;i++)change(a[i].x,a[i].y,a[i].w);    for(int i=2;i<=n;i++){        int t=query(1,id[i]);        if(t==1e9)printf("-1\n");             else printf("%d\n",t-dis[i]);    }    return 0;}
阅读全文
0 0
原创粉丝点击