• 【bzoj1576/Usaco2009 Jan】安全路经Travel——dijkstra+并查集


    Description

    Input

    * 第一行: 两个空格分开的数, N和M

    * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i

    Output

    * 第1..N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最短路经上最后一条牛路的最少的时间.如果这样的路经不存在,输出-1.

    Sample Input

    4 5
    1 2 2
    1 3 2
    3 4 4
    3 2 1
    2 4 3
    输入解释:

    跟题中例子相同

    Sample Output

    3
    3
    6
    输出解释:

    跟题中例子相同
     

     
    先跑一遍dijkstra求出每个点的dis和在最短路树中的dep及fa,
    然后枚举所有非树边->由图(自己画去)易证不经过最后一条边的最短路一定最多只经过一条非树边。
    若我们的源点为S,终点为T,可以发现如果走一条非树边答案为dis[fr]+dis[to]-dis[T]+e[i].w,观察式子可以发现dis[T]至于每个点自身有关,因此可以把dis[fr]+dis[to]+e[i].w作为非树边的权值。
    将非树边按权值从小到大排序,尝试更新fr和to到lca的答案,并查集来实现跳转。
    具体实现方式看代码:
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 #define mem(a,p) memset(a,p,sizeof(a))
     6 const int N=1e5+10,M=2e5+10;
     7 using std::swap;
     8 using std::sort;
     9 struct node{int fr,to,ne,w;}e[M*2],d[M*2];
    10 struct point{
    11     int d,id;
    12     bool operator <(const point&p)const {return p.d<d;}
    13 };
    14 int n,an[N],m,first[N],dis[N],tot=0,fa[N],dep[N],cnt=0;
    15 std::priority_queue<point>q;
    16 int read(){
    17     int ans=0,f=1;char c=getchar();
    18     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    19     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
    20     return ans*f;
    21 }
    22 bool cmp(node a,node b){return a.w<b.w;}
    23 void ins(int u,int v,int w){e[++tot]=(node){u,v,first[u],w};first[u]=tot;}
    24 void dijkstra(){
    25     mem(dis,127);dis[1]=0;q.push((point){0,1});
    26     while(!q.empty()){
    27         point p=q.top();q.pop();
    28         int x=p.id;
    29         for(int i=first[x];i;i=e[i].ne){
    30             int to=e[i].to;
    31             if(dis[to]>dis[x]+e[i].w){
    32                 dis[to]=dis[x]+e[i].w;q.push((point){dis[to],to});
    33                 dep[to]=dep[x]+1;
    34                 fa[to]=x;
    35             }
    36         }   
    37     }
    38 }
    39 int f[N],ans[N];
    40 int getf(int x){
    41     if(f[x]==x)return x;
    42     f[x]=getf(f[x]);
    43     return f[x];
    44 }
    45 int main(){
    46     n=read();m=read();
    47     for(int i=1;i<=n;i++)f[i]=i;
    48     for(int i=1,a,b,c;i<=m;i++){
    49         a=read();b=read();c=read();ins(a,b,c);ins(b,a,c);
    50     }
    51     dijkstra();
    52     for(int i=1;i<=tot;i++){
    53         int x=e[i].fr,y=e[i].to;
    54         if(dep[x]<dep[y])swap(x,y);
    55         if(dis[x]==dis[y]+e[i].w)continue;
    56         d[++cnt]=(node){x,y,0,e[i].w+dis[x]+dis[y]};
    57     }
    58     sort(d+1,d+1+cnt,cmp);
    59     for(int i=1;i<=cnt;i++){
    60         int x=d[i].fr,y=d[i].to;
    61         x=getf(x),y=getf(y);
    62         while(x!=y){
    63             if(dep[x]<dep[y])swap(x,y);
    64             if(!ans[x])ans[x]=d[i].w-dis[x];
    65             x=f[x]=getf(fa[x]);
    66         }
    67     }
    68     for(int i=2;i<=n;i++){
    69         if(!ans[i])printf("-1
    ");
    70         else printf("%d
    ",ans[i]);
    71     }
    72     return 0;
    73 }
    74 
    bzoj1576
  • 相关阅读:
    Django和flask中使用原生SQL方法
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in
    Docker常用命令
    MySQL的压力测试
    使用docker-compose快速搭建PHP开发环境
    Docke如何配置Nginx和PHP
    Docker容器的重命名和自动重启
    docker部署MySQL、Redis和Nginx
    docker-compose的安装卸载以及如何使用
    docker如何制作自己的镜像
  • 原文地址:https://www.cnblogs.com/JKAI/p/7609353.html
Copyright © 2020-2023  润新知