USACO09JAN 安全出行Safe Travel

题目描述

题解:

因为这个东西占的是最短路的最后一条边,我们可以建出最短路树。

一遍dij即可。

如果这个图就是一棵树,那么所有答案全为-1;

所以说非树边更新了答案。

现在让我们开一棵 2,2,4-三甲基-3-乙基戊烷 ,就是#r巨佬的231树。

如果6- - ->7,那3和7的答案都可以由1->2->6- - ->7->3->1更新。

如果7- - ->8,那么只有8的答案可被1->3->7- - ->8->3->1更新。

说白了,如果f- - ->t而且t不是f的祖先,那t到lca(f,t)路径上除了lca的所有点都能被更新。

树链修改,树剖+线段树。

最后dp[i]=min(DP[i])-dis[i];

都表示啥就不说了。

代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100050
#define M 200050
#define ll long long
inline int rd()
{
    int f=1,c=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
    return f*c;
}
int n,m,hed[N],cnt=-1;
struct EG
{
    int f,t,v,nxt;
    bool use;
}e[2*M];
void ae(int f,int t,int v)
{
    e[++cnt].f = f;
    e[cnt].t = t;
    e[cnt].v = v;
    e[cnt].nxt = hed[f];
    hed[f] = cnt;
}
struct node
{
    int x;
    ll d;
    node(){}
    node(int x,ll d):x(x),d(d){}
    friend bool operator < (node a,node b)
    {
        return a.d>b.d;
    }
};
ll dis[N];
bool vis[N];
void dij()
{
    priority_queue<node>q;
    q.push(node(1,0));
    memset(dis,0x3f,sizeof(dis));
    dis[1]=0;
    while(!q.empty())
    {
        node tp = q.top();
        q.pop();
        int u = tp.x;
        if(vis[u])continue;
        vis[u]=1;
        for(int j=hed[u];~j;j=e[j].nxt)
        {
            int to = e[j].t;
            if(dis[to]>dis[u]+e[j].v)
            {
                dis[to]=dis[u]+e[j].v;
                q.push(node(to,dis[to]));
            }
        }
    }
}
bool in_tree[N];
int fa[N];
void build()
{
    queue<int>q;
    q.push(1);
    in_tree[1]=1;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        for(int j=hed[u];~j;j=e[j].nxt)
        {
            int to = e[j].t;
            if(in_tree[to]||dis[to]!=dis[u]+e[j].v)continue;
            in_tree[to]=1;
            e[j].use=1;e[j^1].use=1;
            q.push(to);
        }
    }
}
int siz[N],top[N],son[N],dep[N];
void dfs1(int u,int f)
{
    fa[u]=f;
    dep[u]=dep[f]+1;
    siz[u]=1;
    for(int j=hed[u];~j;j=e[j].nxt)
    {
        int to = e[j].t;
        if(!e[j].use||to==f)continue;
        dep[to]=dep[u]+1;
        dfs1(to,u);
        siz[u]+=siz[to];
        if(siz[to]>siz[son[u]])son[u]=to;
    }
}
int tin[N],tim,pla[N];
void dfs2(int u,int tp)
{
    top[u]=tp;tin[u]=++tim;pla[tim]=u;
    if(son[u])
    {
        dfs2(son[u],tp);
        for(int j=hed[u];~j;j=e[j].nxt)
        {
            int to = e[j].t;
            if(!e[j].use||to==son[u]||to==fa[u])continue;
            dfs2(to,to);
        }
    }
}
int get_lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        x=fa[top[x]];
    }
    return dep[x]<dep[y]?x:y;
}
const ll inf = 0x3f3f3f3f3f3f3f3fll;
ll dp[N];
struct segtree
{
    ll v[N<<2],tag[N<<2];
    void renew(int u,ll d)
    {
        if(d<v[u])
        {
            v[u]=d;
            tag[u]=d;
        }
    }
    void pushdown(int u)
    {
        if(tag[u]!=inf)
        {
            renew(u<<1,tag[u]);
            renew(u<<1|1,tag[u]);
            tag[u]=inf;
        }
    }
    void build(int l,int r,int u)
    {
        v[u]=tag[u]=inf;
        if(l==r)return ;
        int mid = (l+r)>>1;
        build(l,mid,u<<1);
        build(mid+1,r,u<<1|1);
    }
    void insert(int l,int r,int u,int ql,int qr,ll d)
    {
        if(l==ql&&r==qr)
        {
            renew(u,d);
            return ;
        }
        pushdown(u);
        int mid = (l+r)>>1;
        if(qr<=mid)insert(l,mid,u<<1,ql,qr,d);
        else if(ql>mid)insert(mid+1,r,u<<1|1,ql,qr,d);
        else insert(l,mid,u<<1,ql,mid,d),insert(mid+1,r,u<<1|1,mid+1,qr,d);
    }
    void print(int l,int r,int u)
    {
        if(l==r)
        {
            dp[pla[l]] = v[u]-dis[pla[l]];
            return ;
        }
        pushdown(u);
        int mid = (l+r)>>1;
        print(l,mid,u<<1);
        print(mid+1,r,u<<1|1);
    }
}tr;
int main()
{
    n=rd(),m=rd();
    memset(hed,-1,sizeof(hed));
    for(int f,t,v,i=1;i<=m;i++)
    {
        f=rd(),t=rd(),v=rd();
        ae(f,t,v),ae(t,f,v);
    }
    dij();
    build();
    dfs1(1,0);
    dfs2(1,1);
    tr.build(1,n,1);
    for(int f,t,j=0;j<=cnt;j++)
    {
        if(e[j].use)continue;
        f = e[j].f,t = e[j].t;
        int lca = get_lca(f,t);
        if(lca==t)continue;
        ll tmp = dis[f]+dis[t]+e[j].v;
        int now=top[t];
        while(dep[now]>dep[lca])
        {
            tr.insert(1,n,1,tin[now],tin[t],tmp);
            t = fa[now],now = top[t];
        }
        if(dep[t]>dep[lca])
            tr.insert(1,n,1,tin[lca]+1,tin[t],tmp);
    }
    tr.print(1,n,1);
    for(int i=2;i<=n;i++)
    {
        if(dp[i]>10000000000ll)dp[i]=-1;
        printf("%lld\n",dp[i]);
    }
    return 0;
}

 

posted @ 2018-12-21 13:26  LiGuanlin  阅读(347)  评论(1编辑  收藏  举报