zoukankan      html  css  js  c++  java
  • [bzoj1576]安全路径

    先建立最短路径树(即跑dij每一个点向更新他的点连边),考虑一个点的答案路径一定要走过且仅走过一条非树边,枚举非树边(x,y),对于一个点k,如果它在x~lca(y~lca的路径上同理),那么答案可以更改为s[y]+len(x,y)+s[x]-s[k],前三个不受k的影响,因此越小越好,即将每一条边按照这个排序后依次加入,用并查集来维护即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 #define L (k<<1)
     5 #define R (L+1)
     6 #define mid (l+r>>1)
     7 int E,n,m,x,y,z,k,d[N],fa[N],f[N],head[N],ans[N];
     8 struct ji{
     9     int x,y;
    10     bool operator < (const ji &a)const{
    11         return y>a.y;
    12     }
    13 };
    14 struct ji2{
    15     int fr,nex,to,len;
    16     bool operator < (const ji2 &a)const{
    17         return len+d[fr]+d[to]<a.len+d[a.fr]+d[a.to];
    18     }
    19 }edge[N<<2];
    20 priority_queue<ji>q;
    21 void add(int x,int y,int z){
    22     edge[E]=ji2{x,head[x],y,z};
    23     head[x]=E++;
    24 }
    25 int find(int k){
    26     if (k==f[k])return k;
    27     return f[k]=find(f[k]);
    28 }
    29 int main(){
    30     scanf("%d%d",&n,&m);
    31     memset(head,-1,sizeof(head));
    32     for(int i=1;i<=m;i++){
    33         scanf("%d%d%d",&x,&y,&z);
    34         add(x,y,z);
    35         add(y,x,z);
    36     }
    37     memset(d,0x3f,sizeof(d));
    38     q.push(ji{d[1]=0,1});
    39     while (!q.empty()){
    40         x=q.top().y;
    41         q.pop();
    42         for(int j=head[x];j!=-1;j=edge[j].nex)
    43             if (d[edge[j].to]>d[x]+edge[j].len){
    44                 fa[edge[j].to]=x;
    45                 q.push(ji{d[edge[j].to]=d[x]+edge[j].len,edge[j].to});
    46             }
    47     }
    48     sort(edge,edge+E);
    49     memset(ans,-1,sizeof(ans));
    50     for(int i=1;i<=n;i++)f[i]=i;
    51     for(int i=0;i<E;i++)
    52         if ((fa[edge[i].to]!=edge[i].fr)&&(fa[edge[i].fr]!=edge[i].to)){
    53             x=find(edge[i].fr);
    54             y=find(edge[i].to);
    55             z=edge[i].len+d[edge[i].fr]+d[edge[i].to];
    56             while (x!=y){
    57                 if (d[x]<d[y])swap(x,y);
    58                 ans[x]=z-d[x];
    59                 f[find(x)]=find(fa[x]);
    60                 x=find(x);
    61             }
    62         }
    63     for(int i=2;i<=n;i++)printf("%d\n",ans[i]);
    64 }
    View Code
  • 相关阅读:
    新概念 Lesson 2 Sorry, sir.
    记一次无法正常本地登陆Linux服务器(确定密码正确)
    English trip -- VC(情景课)5 D
    新概念 Lesson 1 Excuse me!
    English trip -- VC(情景课)5 C It's on Main Street 在主街上
    English trip -- Iris老师整理的一般时态
    English trip -- VC(情景课)5 B Places around town 城市设施
    English trip -- VC(情景课)5 Around Town
    Ploya定理学习笔记
    莫比乌斯反演学习笔记
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11249608.html
Copyright © 2011-2022 走看看