bzoj2725(最短路+线段树)

题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=2725

题解

先随便抽个 $S$ 到 $T$ 的最短路出来

如果删的边不在这个最短路上显然没有影响

如果在这个最短路上,那么构造最短路图,是个 $DAG$ 图

最坏的情况是最短路边长,此时只有一条边为非树边

证明可以用反证法,设绕过的非树边为 $$ ,那么 $S$ 到 $x$ 的路径在 $S$ 的最短路径树上,$y$ 到 $T$ 的路径在 $T$ 的最短路径数上

那么只要枚举一条边就可以了,如果能枚举到 $DAG$ 图上的边说明最短路不变

现在就剩下处理每条边能代替原最短路的哪些边了。。

设 $g_s[x]$ 表示离 $x$ 最近的最短路上的点,$g_t[x]$ 同理

那么影响的范围就是 $[g_s[x],g_t[x]]$ ,变成区间更新问题,直接线段树维护即可




代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
*         ┏┓    ┏┓
*         ┏┛┗━━━━━━━┛┗━━━┓
*         ┃       ┃  
*         ┃   ━    ┃
*         ┃ >   < ┃
*         ┃       ┃
*         ┃... ⌒ ...  ┃
*         ┃ ┃
*         ┗━┓ ┏━┛
*          ┃ ┃ Code is far away from bug with the animal protecting          
*          ┃ ┃ 神兽保佑,代码无bug
*          ┃ ┃           
*          ┃ ┃       
*          ┃ ┃
*          ┃ ┃           
*          ┃ ┗━━━┓
*          ┃ ┣┓
*          ┃ ┏┛
*          ┗┓┓┏━━━━━━━━┳┓┏┛
*           ┃┫┫ ┃┫┫
*           ┗┻┛ ┗┻┛
*/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<set>
#include<bitset>
#include<complex>
#include<assert.h>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1<<x)
#define mid (x+y>>1)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define NM 200005
#define nm 400005
using namespace std;
const double pi=acos(-1);
const ll inf=1e18;
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}



struct edge{int t;ll v;edge*next;}e[nm],*h[NM],*o=e;
void add(int x,int y,ll v){o->t=y;o->v=v;o->next=h[x];h[x]=o++;}
int n,m,g[NM],_g[NM],_x,_y,id[NM],S,T,tot,a[NM],p[NM];
ll d[NM],_d[NM],_t;


struct tmp{
int x;ll d;
bool operator<(const tmp&o)const{return d>o.d;}
};
priority_queue<tmp>q;
void dij(int u){
inc(i,1,n)d[i]=inf;
q.push(tmp{u,d[u]=0});
while(!q.empty()){
int t=q.top().x;q.pop();
link(t)if(d[j->t]>d[t]+j->v)q.push(tmp{j->t,d[j->t]=d[t]+j->v}),p[j->t]=t;
}
}
void dfs(int x){
link(x)if(!g[j->t]&&d[j->t]==d[x]+j->v)g[j->t]=g[x],dfs(j->t);
}


struct node{
int x,y;ll s;
node*l,*r;
node(int x,int y,node*l=0,node*r=0):x(x),y(y),l(l),r(r),s(inf){}
void push(){l->s=min(l->s,s);r->s=min(r->s,s);}
void mod(){
if(_y<x||y<_x)return;
if(_x<=x&&y<=_y){s=min(s,_t);return;}
l->mod();r->mod();
}
void out(){
if(x==y){_d[x]=s;return;}
push();l->out();r->out();
}
}*root;
node*build(int x,int y){return x==y?new node(x,y):new node(x,y,build(x,mid),build(mid+1,y));}


int main(){
n=read();m=read();
inc(i,1,m){_x=read();_y=read();_t=read();add(_x,_y,_t);add(_y,_x,_t);}
S=read();T=read();
if(S==T)goto la;
dij(S);
for(int x=T;x!=S;x=p[x]){
id[x]=++tot;a[tot]=x;
}
id[S]=++tot;a[tot]=S;
dec(i,tot,1)g[a[i]]=a[i];
dec(i,tot,1)dfs(a[i]);
inc(i,1,n)_d[i]=d[i];
inc(i,1,n)_g[i]=g[i];
dij(T);mem(g);
inc(i,1,tot)g[a[i]]=a[i];
inc(i,1,tot)dfs(a[i]);
root=build(1,tot-1);
inc(i,1,n)link(i)if(!id[i]||!id[j->t]||abs(d[i]-d[j->t])<+j->v){
_x=id[g[j->t]];_y=id[_g[i]]-1;_t=_d[i]+d[j->t]+j->v;
//printf("%d %d:%d %d %lld\n",i,j->t,_x,_y,_t);
if(_x>_y)continue;
root->mod();
}
inc(i,1,tot-1)_d[i]=inf;
root->out();
la:
m=read();while(m--){
_x=read();_y=read();
if(id[_x]&&id[_y]&&abs(id[_x]-id[_y])==1){
if(_d[min(id[_x],id[_y])]<inf)printf("%lld\n",_d[min(id[_x],id[_y])]);
else printf("Infinity\n");
}else{
if(d[S]<inf)printf("%lld\n",d[S]);else printf("Infinity\n");
}
}
return 0;
}