jzoj3500-物语【最短路】

正题

题目链接:https://jzoj.net/senior/#contest/show/3005/0


题目大意

n n 个点 m m 条边的无向图,有一条边的边权会变化, q q 次变化,每次询问最短路。


解题思路

可变边 ( x , y ) (x,y)
路径无非就三种

  1. 1 > n 1->n
  2. 1 > x > y > n 1->x->y->n
  3. 1 > y > x > n 1->y->x->n

1 1 n n 都跑一次最短路就好了。


c o d e code

#pragma GCC optimize(2)
%:pragma GCC optimize(3)
%:pragma GCC optimize("Ofast")
%:pragma GCC optimize("inline")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cctype>
#define ll long long
using namespace std;
const ll N=5e5+10;
struct edge_node{
	ll to,next,w;
}a[N*2];
struct node{
	ll pos,dis;
};
bool operator<(node x,node y)
{return x.dis>y.dis;}
ll read() {
	ll x=0,f=1; char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
	while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
	return x*f;
}
ll n,m,Q,f1[N],f2[N],ls[N],s,t,tot;
bool v[N];
priority_queue<node> q;
void addl(ll x,ll y,ll w){
	a[++tot].to=y;
	a[tot].next=ls[x];
	ls[x]=tot;
	a[tot].w=w;
	return;
}
void dij(ll s,ll *f){
	memset(v,0,sizeof(v));
	q.push((node){s,0});f[s]=0;
	while(!q.empty()){
		ll x=q.top().pos;q.pop();
		if(v[x]) continue;v[x]=1;
		for(ll i=ls[x];i;i=a[i].next){
			ll y=a[i].to;
			if(f[x]+a[i].w<f[y]){
				f[y]=f[x]+a[i].w;
				if(!v[y])
					q.push((node){y,f[y]});
			}
		}
	}
	return;
}
int main()
{
	freopen("monogatari.in","r",stdin);
	freopen("monogatari.out","w",stdout);
	n=read();m=read();Q=read();
	for(int i=1;i<=n;i++)
		f1[i]=f2[i]=1e18;
	for(ll i=1;i<m;i++){
		ll x=read(),y=read(),w=read();
		addl(x,y,w);addl(y,x,w);
	}
	dij(1,f1);dij(n,f2);
	s=read();t=read();
	while(Q--){
		ll w=read(),ans=f1[n];
		ans=min(min(f1[s]+f2[t]+w,f1[t]+f2[s]+w),ans);
		if(ans>=1e18) printf("+Inf\n");
		else printf("%lld\n",ans);
	}
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/104160572