bzoj 1576[Usaco2009 Jan]安全路经Travel

其实很久之前做的了,但是怎么都不过,今天拿出来竟然改一下就过了= =||

大概就是 给了一张无向图,问从起点开始到每个点的次短路。首先我们dij处理处最短路径树,然后在这上面搞事情处理一下。枚举所有的非树边 设起点u终点v 则这条边可以更新所有LCA(u,v)到v的点的次短路,就是dis[u]+len+dis[v]-dis[i] 这个i是正在处理的点 dis表示到根的距离 但是每条非树边可以更新的点有点多,所以我们要树剖维护这个过程 ,就是更新 所有LCA(u,v)到v的点 然后你就挂了 不能带着lca!  不能带着lca!  不能带着lca! 就这个把我挂哭了

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
# define inf 0x3f3f3f3f
using namespace std;
const int maxn=100000+10;
struct node{int to,next,len,fr;bool o;}table[maxn<<2];
struct tree{int x,l,r;int mn,lazy;}t[maxn<<2];
int tot,head[maxn];
void add(int a,int b,int c){table[++tot]=(node){b,head[a],c,a};head[a]=tot;}
int n,m;
char s[1<<25];
inline long long read()
{
    static char *c=s;
    if(c==s) fread(c,1,1<<25,stdin);
    long long u=0;
    while(*c<48) ++c;
    while(*c>32) u=u*10+*c++-48;
    return u;
}
typedef pair<int,int>Pair;
priority_queue<Pair,vector<Pair>,greater<Pair> >Q;
int d[maxn],fr[maxn];
bool v[maxn];
void dij()
{
    memset(d,0x3f,sizeof d);
    d[1]=0; Q.push(make_pair(d[1],1));
    while(!Q.empty())
    {
        Pair top=Q.top();
        Q.pop();
        int x=top.second;
        if(v[x]) continue;
        v[x]=1;
        for(int i=head[x];i;i=table[i].next)
        if(d[table[i].to]>d[x]+table[i].len)
        {
            d[table[i].to]=d[x]+table[i].len;
            table[i].o=1;
            table[fr[table[i].to]].o=0;
            fr[table[i].to]=i;
            Q.push(make_pair(d[table[i].to],table[i].to));
        }
    }
}
int f[maxn],dep[maxn],son[maxn],tp[maxn],w[maxn],pos[maxn],siz[maxn],cnt;
int ans[maxn][20];
void dfs1(int x)
{
    dep[x]=dep[f[x]]+1;
    siz[x]=1;
    for(int i=1;i<=16;i++)
    {
        if(dep[x]<(1<<i)) break;
        ans[x][i]=ans[ans[x][i-1]][i-1];    
    }
    for(int i=head[x];i;i=table[i].next)
    if(table[i].o&&table[i].to!=f[x])
    {
        f[table[i].to]=x;
        ans[table[i].to][0]=x;
        dfs1(table[i].to);
        siz[x]+=siz[table[i].to];
        if(siz[table[i].to]>siz[son[x]]) son[x]=table[i].to;
    }
}
void dfs2(int x)
{
    w[pos[x]=++cnt]=x;
    if(x==son[f[x]]) tp[x]=tp[f[x]];
    else tp[x]=x;
    if(son[x]) dfs2(son[x]);
    for(int i=head[x];i;i=table[i].next)
    if(table[i].to!=son[x]&&table[i].o&&table[i].to!=f[x]) dfs2(table[i].to);
}
void maketree(int x,int l,int r)
{
    t[x].l=l; t[x].r=r; t[x].lazy=t[x].mn=inf;
    if(l==r) return ;
    int mid=(t[x].l+t[x].r)>>1;
    maketree(x<<1,l,mid);
    maketree(x<<1|1,mid+1,r);
}
int LCA(int x,int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    int l=dep[x]-dep[y];
    for(int i=0;i<=16;i++)
    if(l&(1<<i)) x=ans[x][i];
    for(int i=16;i>=0;i--)
    if(ans[x][i]!=ans[y][i]) x=ans[x][i],y=ans[y][i];
    return x==y?x:ans[x][0];    
}
void pushdown(int x)
{
    if(t[x].lazy==inf) return ;
    int lc=x<<1,rc=x<<1|1;
    t[lc].lazy=min(t[lc].lazy,t[x].lazy);
    t[rc].lazy=min(t[rc].lazy,t[x].lazy);
    t[lc].mn=min(t[lc].mn,t[x].lazy);
    t[rc].mn=min(t[rc].mn,t[x].lazy);
}
void change(int x,int l,int r,int tar)
{
    if(t[x].l==l&&t[x].r==r)
    {
        t[x].lazy=min(t[x].lazy,tar);
        if(l==r) t[x].mn=min(t[x].mn,tar);
        return ;
    }
    pushdown(x);
    int mid=(t[x].l+t[x].r)>>1;
    if(r<=mid) change(x<<1,l,r,tar);
    else if(l>mid) change(x<<1|1,l,r,tar);
    else change(x<<1,l,mid,tar),change(x<<1|1,mid+1,r,tar);
}
void modify(int x,int lca,int tar)
{
    int fx=tp[x];
    while(dep[fx]>dep[lca])
    {
        change(1,pos[fx],pos[x],tar);
        x=f[fx],fx=tp[x];
    }
    if(x!=lca) change(1,pos[lca]+1,pos[x],tar);
}
int search(int x,int pos)
{
    if(t[x].l==t[x].r) return t[x].mn;
    pushdown(x);
    int mid=(t[x].l+t[x].r)>>1;
    if(pos<=mid) return search(x<<1,pos);
    else return search(x<<1|1,pos);    
}
int main()
{
    scanf("%d%d",&n,&m);
    int a,b,c;
    for(int i=1;i<=m;i++)
    {
        a=read(); b=read(); c=read();
        add(a,b,c); add(b,a,c);
    }
    dij();
    dfs1(1);
    dfs2(1);
    maketree(1,1,cnt);
    for(int i=1;i<=tot;i++)
    if(!table[i].o)
    {
        int t=LCA(table[i].fr,table[i].to);
        modify(table[i].to,t,d[table[i].fr]+table[i].len+d[table[i].to]);
    }
    for(int i=2;i<=n;i++)
    {
        int x=search(1,pos[i]);
        if(x==inf) puts("-1");
        else printf("%d\n",x-d[i]);
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值