题解 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;
}
posted @ 2021-11-08 22:32  pidan007  阅读(41)  评论(0编辑  收藏  举报