• [USACO09JAN]安全出行Safe Travel(最短路径树)


    传送门

    求对于每个点删掉1到他的最短路上的最后一条边(就是这条路径上与他自己相连的那条边)后1到他的最短路的长度。

    即:最短路径树:图中的源点到所有结点的最短路径构成的树。

    最短路径树在dijkstra过程中就可以求出来,因为这个过程就相当于走一棵树。

    然后就是选入杂边,对于一条杂边<u,v>,它加入后会形成一个环,这个环上所有的点除了lca都可以被这条杂边更新,即这些点删去它上面那条边后是可以走杂边的,但lca删去上面那条边后图就不连通了。

    那么

    disnew[x]=dis[u]+dis[v]+w[i]−dis[x]

    对于一条杂边,前面那三个量是一定的。 每一个点,我们希望用最小的杂边更新他,更新过后就不再更新。 于是可以按w排序杂边,依次更新,更新过后的点就用并查集缩起来,以保证每个点只被更新一次。

    //要题目中说了源点到每个点最短路径是唯一的 那往往都和最短路树有关系
    #include<bits/stdc++.h>
    #define N 100003
    #define M 200003
    #define INF 2100000000
    using namespace std;
    int read()
    {
        int x=0,f=1;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    int tot=1,n;
    int head[N],dis[N],ans[N],dep[N],fa[N],pre[N],anc[N],ontree[M*2];
    struct EDGE{
        int nextt,to,val;
    }w[M*2];
    struct Edge{
        int u,v,val;
    }za[M*2];
    struct qnode{
        int v,c;
        qnode(int _v=0,int _c=0):v(_v),c(_c){} 
        bool operator <(const qnode &r)const
        {
            return r.c<c;
        }
    };
    bool cmp(const Edge &a,const Edge &b)
    {
        return a.val<b.val;
    }
    void add(int a,int b,int c)
    {
        tot++;
        w[tot].nextt=head[a];
        w[tot].to=b;
        w[tot].val=c;
        head[a]=tot;
    }
    int get(int x)
    {
        if(fa[x]==x)return x;
        return fa[x]=get(fa[x]);
    }
    void dij()
    {
        priority_queue<qnode>q;
        for(int i=1;i<=n;++i)dis[i]=INF;
        dis[1]=0;
        q.push(qnode(1,0));
        while(!q.empty())
        {
            qnode e=q.top();q.pop();
            int u=e.v;
            for(int i=head[u];i;i=w[i].nextt)
            {
                int v=w[i].to;
                if(dis[v]>dis[u]+w[i].val)
                {
                    dis[v]=dis[u]+w[i].val;
                    pre[v]=i;anc[v]=u;dep[v]=dep[u]+1;
                    q.push(qnode(v,dis[v]));
                }
            }
        }
    }
    int main()
    {
          n=read();int m=read();
          for(int i=1;i<=m;++i)
          {
              int a=read(),b=read(),c=read();
              add(a,b,c);add(b,a,c);
        }
        dij();
        
        for(int i=2;i<=n;++i)ontree[pre[i]]=1;
        for(int i=1;i<=n;++i)fa[i]=i,ans[i]=INF;
        int cnt=0;
        for(int i=2;i<=tot;++i)
          if(!ontree[i]&&!ontree[i^1])
          {
              za[++cnt].u=w[i].to;
              za[cnt].v=w[i^1].to;
              za[cnt].val=dis[w[i].to]+dis[w[i^1].to]+w[i].val;
          }
        sort(za+1,za+1+cnt,cmp);
        for(int i=1;i<=cnt;++i)
        {
            int u=za[i].u,v=za[i].v;
            u=get(u);v=get(v);
            while(u!=v)
            {
                if(dep[u]<dep[v])swap(u,v);//从下往上并上去 
                ans[u]=min(ans[u],za[i].val-dis[u]);
                u=fa[u]=get(anc[u]);
            }
        }
        for(int i=2;i<=n;++i)
        {
            if(ans[i]<INF)printf("%d
    ",ans[i]);
            else printf("-1
    ");
        }
    } 
    View Code
  • 相关阅读:
    mvc:三
    mvc:二
    Linq分组,linq方法分组
    Linq 中按照多个值进行分组(GroupBy)
    Photoshop 字体
    报表Reporting S而vice是 错误的解决
    1*书籍装帧
    photoshop 魔术橡皮擦
    Photoshop 钢笔 双窗口显示
    数字格式化
  • 原文地址:https://www.cnblogs.com/yyys-/p/11387343.html
Copyright © 2020-2023  润新知