【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
原文地址:https://www.cnblogs.com/JKAI/p/7609353.html