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

Posted yyys-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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\\n",ans[i]);
        else printf("-1\\n");
    
 
View Code

 

以上是关于[USACO09JAN]安全出行Safe Travel(最短路径树)的主要内容,如果未能解决你的问题,请参考以下文章

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

P2934 [USACO09JAN]安全出行

[usaco jan 09] 安全路径 travel [最短路径树]

WOJ#2423 安全出行Safe Travel

[Usaco2009 Jan]安全路经Travel

BZOJ1576 [Usaco2009 Jan]安全路经Travel