题解 CF1163F Indecisive Taxi Fee
题解 CF1163F Indecisive Taxi Fee
题意描述:
给定一张 \(n\) 个点, \(m\) 条边的带权无向图。
\(q\) 组询问,每次给出两个数 \(t,x\) ,求出将边 \(t\) 的长度修改为 \(x\) 后 \(1\to n\) 的最短路。
\(2\leq n\leq 2\times 10^5,1\leq m,q\leq 2\times 10^5,w\leq 10^9\)
动态最短路。
先分类讨论一下:
设 \(len\) 为原最短路长
- 若 \(t\) 在最短路上
- 若 \(x\leq w_t\) 答案显然就是 \(len-w_t+x\)
- 若 \(x>w_t\) 则答案要从其它路径和修改边权后的最短路中取最小值
- 若 \(t\) 不在最短路上
- 若 \(x\leq w_t\) 答案为 \(\min\{len,\min\{dist_{1,u_i}+x+dist_{v_i,n},dist_{1,v_i}+x+dist_{u_i,n}\}\}\)
- 若 \(x>w_t\) 答案依然为 \(len\)
发现只有 \(t\) 在最短路上且 \(x>w_t\) 的情况比较难搞,于是我们考虑强制不走最短路上某条边的新最短路。
这里有一个结论:新最短路一定是从 \(1\) 走到最短路上某一点 \(l\) ,然后跳出最短路,使得路径不经过 \(t\) ,走一段后回到最短路上 \(r\) ,再走到 \(n\) 。
读者自证不难。
好吧就算完全不走原最短路,也可看做 \(1\to 1\) 再 \(n\to n\),所以显然成立。
我们发现对于不在最短路上的一条边,对应的 \(l,r\) 是固定的,可以预处理出来,具体地,先跑一遍 \(n\to 1\) 的最短路,把最短路抠出来,显然最短路上的边的 \(l,r\) 就是下标,当某一个点跳出最短路时,所走边 \(l/r\) 就是它的前驱的 \(l/r\) ,正反两遍 \(Dijkstra\) 解决。
现在考虑用非最短路边更新最短路上的答案,强制走非最短路边 \(i\) 的答案是区间修改 \(\min\limits_{l_{u_i}+1\leq x\leq r_{v_i}}Min_x\) ,线段树区间修改,单点查询最小值即可。
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 0x3f3f3f3f3f3f3f3f
#define N 400005
#define ls k<<1
#define rs k<<1|1
#define mid ((l+r)>>1)
#define mp make_pair
#define rg register
#define il inline
#define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
il int read(){
int w=0,h=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')h=-h;ch=getchar();}
while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
return w*h;
}
struct edge{
int next,to,id,val;
}edge[N<<1];
struct node{
int u,v,w;
}e[N];
int n,m,q;
int head[N],num;
void add(int u,int v,int w,int id){
edge[++num].next=head[u];
edge[num].to=v;
edge[num].id=id;
edge[num].val=w;
head[u]=num;
}
namespace Dijkstra{
int dist[N][2],from[N];
int L[N],R[N],seg[N],cnt;
bool vis[N],path[N];
priority_queue<pair<int,int> >q;
void dij_pre(){
memset(dist,inf,sizeof(dist));
memset(vis,0,sizeof(vis));
dist[n][0]=0;
q.push(mp(0,n));
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;
vis[u]=1;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(dist[u][0]+edge[i].val<dist[v][0]){
dist[v][0]=dist[u][0]+edge[i].val;
from[v]=edge[i].id;
q.push(mp(-dist[v][0],v));
}
}
}
}
void back(){
path[1]=1;
L[1]=R[1]=0;
int u=1;
for(int i=1;u!=n;i++){
int fr=from[u];
seg[fr]=i;
cnt++;
u=e[fr].u^e[fr].v^u;
path[u]=1;
L[u]=R[u]=i;
}
}
void dij(int ty){
memset(vis,0,sizeof(vis));
dist[ty?n:1][ty]=0;
q.push(mp(0,ty?n:1));
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;
vis[u]=1;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(dist[u][ty]+edge[i].val<dist[v][ty]){
dist[v][ty]=dist[u][ty]+edge[i].val;
if(!path[v])
ty?R[v]=R[u]:L[v]=L[u];
q.push(mp(-dist[v][ty],v));
}
}
}
}
}
namespace SGT{
int Min[N<<2];
void build(int k,int l,int r){
Min[k]=inf;
if(l==r)return;
build(ls,l,mid);
build(rs,mid+1,r);
}
void modify(int k,int l,int r,int x,int y,int v){
if(l>r||x>y)return;
if(l>=x&&r<=y){
Min[k]=min(Min[k],v);
return;
}
if(x<=mid)modify(ls,l,mid,x,y,v);
if(mid<y)modify(rs,mid+1,r,x,y,v);
}
int query(int k,int l,int r,int x){
if(l==r)return Min[k];
int res=Min[k];
if(x<=mid)res=min(res,query(ls,l,mid,x));
if(mid<x)res=min(res,query(rs,mid+1,r,x));
return res;
}
}
signed main(){
n=read();m=read();q=read();
for(int i=1;i<=m;i++){
int u=read(),v=read(),w=read();
add(u,v,w,i);add(v,u,w,i);
e[i]=(node){u,v,w};
Dijkstra::seg[i]=-1;
}
Dijkstra::dij_pre();
Dijkstra::back();
memset(Dijkstra::dist,inf,sizeof(Dijkstra::dist));
Dijkstra::dij(0);
Dijkstra::dij(1);
SGT::build(1,1,Dijkstra::cnt);
for(int i=1;i<=m;i++)
if(Dijkstra::seg[i]==-1){
SGT::modify(1,1,Dijkstra::cnt,Dijkstra::L[e[i].u]+1,Dijkstra::R[e[i].v],Dijkstra::dist[e[i].u][0]+e[i].w+Dijkstra::dist[e[i].v][1]);
SGT::modify(1,1,Dijkstra::cnt,Dijkstra::L[e[i].v]+1,Dijkstra::R[e[i].u],Dijkstra::dist[e[i].v][0]+e[i].w+Dijkstra::dist[e[i].u][1]);
}
for(int i=1;i<=q;i++){
int rd=read(),va=read(),ans=Dijkstra::dist[n][0];
if(~Dijkstra::seg[rd]){
ans=ans-e[rd].w+va;
if(va>e[rd].w)
ans=min(ans,SGT::query(1,1,Dijkstra::cnt,Dijkstra::seg[rd]));
}
else
if(va<e[rd].w){
ans=min(ans,Dijkstra::dist[e[rd].u][0]+va+Dijkstra::dist[e[rd].v][1]);
ans=min(ans,Dijkstra::dist[e[rd].v][0]+va+Dijkstra::dist[e[rd].u][1]);
}
printf("%lld\n",ans);
}
return 0;
}