JZOJ 3500.【NOIP2013模拟联考15】物语(monogatari)

D e s c r i p t i o n Description Description

给定一个 G ( n , m ) G(n,m) G(n,m)的无向图,其中第 m m m条边的边权会改变,求1到 n n n的最短路

数据范围: n ≤ 2 × 1 0 5 , m ≤ 5 × 1 0 5 , k ≤ 3 × 1 0 5 n\leq 2\times 10^5,m\leq 5\times 10^5,k\leq 3\times 10^5 n2×105,m5×105,k3×105


S o l u t i o n Solution Solution

记会变的那条边为 ( x , y , z s i ) (x,y,zs_i) (x,y,zsi)

分类讨论走不走 x , y x,y x,y这条边即可

d i j dij dij,时间复杂度: O ( n l o g m + q ) O(nlogm+q) O(nlogm+q)


C o d e Code Code
#pragma GCC optimize(2)
%:pragma GCC optimize(3)
%:pragma GCC optimize("Ofast")
%:pragma GCC optimize("inline")
#include<queue>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define N 2000010
#define M 1600010
using namespace std;int n,m,k,l[N],tot,x,y;
struct node{int next,to;LL w;}e[M*2];
inline void add(int u,int v,LL w){e[++tot]=(node){l[u],v,w};l[u]=tot;return;}
LL z,ans,zs[M],dis[N],len1,len2,len3,len4,len5;
bool vis[N];struct heap{int u;LL d;};
inline bool operator <(heap x,heap y){return x.d>y.d;}
inline LL read()
{
	char c;LL d=1,f=0;
	while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
inline void dij(int s)
{
	for(register int i=1;i<=n;i++) dis[i]=1e16,vis[i]=0;
	dis[s]=0;
	priority_queue<heap>q;
	q.push((heap){s,0});
	while(q.size())
	{
		heap u=q.top();q.pop();
		int x=u.u,d=u.d;if(vis[x]) continue;vis[x]=true;
		for(register int i=l[x];i;i=e[i].next)
		{
			int y=e[i].to;LL w=e[i].w;
			if(dis[x]+w<dis[y])
			{
				dis[y]=dis[x]+w;
				q.push((heap){y,dis[y]});
			}
		}
	}
	return;
}
inline void print(LL x)
{
	if(x>=1e16) puts("+Inf");
	else printf("%lld\n",x);
	return;
}
signed main()
{
	freopen("monogatari.in","r",stdin);
	freopen("monogatari.out","w",stdout);
	n=read();m=read();k=read();
	for(register int i=1;i<m;i++)
	{
		x=read();y=read();z=read();
		add(x,y,z);add(y,x,z);
	}
	x=read();y=read();
	for(register int i=1;i<=k;i++) zs[i]=read();
	dij(1);
	len1=dis[n];len2=dis[x];len3=dis[y];
	dij(n);
	len4=dis[x];len5=dis[y];
	for(register int i=1;i<=k;i++) print(min(len1,min(len2+zs[i]+len5,len3+zs[i]+len4)));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值