洛谷 [HNOI2014]道路堵塞 解题报告

[HNOI2014]道路堵塞

题意

给一个有向图并给出一个这个图的一个(1sim n)最短路,求删去这条最短路上任何一条边后的最短路。


又事SPFA玄学...

有个结论,新的最短路一定是(1sim l,lsim r,rsim n)组成的,中间一段是非最短路,两边是原最短路

先删去最短路

然后从1开始枚举短边,按顺序维护(1sim i)(i)个点连到(rsim n)的最小值,发现我们要根据(r)的变换进行删除,可以拿一个堆维护。

剩下的对每个点跑跑(SPFA)就可以了,每次注意删去不参与松弛的那条边。

感性上是只跑了一次(SPFA)


Code:

#include <cstdio>
#include <cstring>
#include <queue>
#include <cctype>
int read()
{
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
}
const int N=2e5+10;
int head[N],to[N],Next[N],edge[N],cnt;
void add(int u,int v,int w)
{
    to[++cnt]=v,edge[cnt]=w,Next[cnt]=head[u],head[u]=cnt;
}
struct node{int u,v,w;}E[N];
int n,m,L,used[N],dis[N],disl[N],disr[N],num[N],ban[N],path[N],s[N],vis[N],tot;
struct yuucute
{
	int v,w;
	bool friend operator <(yuucute a,yuucute b){return a.w>b.w;}
}yuu[N];
std::priority_queue <yuucute> Q;
void spfa(int ss,int ban,int tim)
{
	dis[ss]=disl[ss];
	std::queue <int> q;
	q.push(ss);
	tot=0;
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		used[now]=0;
		for(int v,i=head[now];i;i=Next[i])
			if(((v=to[i])!=ban||now!=ss)&&dis[v]>dis[now]+edge[i])
			{
				dis[v]=dis[now]+edge[i];
				if(num[v]>tim){if(vis[v]!=tim) vis[s[++tot]=v]=tim;}
				else if(!used[v]) {q.push(v);used[v]=1;}
			}
	}
	while(tot)
	{
		int now=s[tot--];
		if(!yuu[now].v||yuu[now].w>dis[now]+disr[now])
		{
			yuu[now].w=dis[now]+disr[now];
			yuu[now].v=now;
			Q.push(yuu[now]);
		}
	}
}
int main()
{
	n=read(),m=read(),L=read();
	for(int i=1;i<=m;i++) E[i].u=read(),E[i].v=read(),E[i].w=read();
	for(int i=1;i<=L;i++)
	{
		ban[path[i]=read()]=1;
		num[E[path[i]].u]=i;
		disl[E[path[i]].v]=disl[E[path[i]].u]+E[path[i]].w;
	}
	num[n]=L+1;
	for(int i=L;i;i--) disr[E[path[i]].u]=disr[E[path[i]].v]+E[path[i]].w;
	for(int i=1;i<=m;i++) if(!ban[i]) add(E[i].u,E[i].v,E[i].w);
	memset(dis,0x3f,sizeof dis);
	for(int i=1;i<=L;i++)
	{
		spfa(E[path[i]].u,E[path[i]].v,i);
		while(!Q.empty()&&num[Q.top().v]<=i) Q.pop();
		if(Q.empty()) puts("-1");
		else printf("%d
",Q.top().w);
	}
	return 0;
}

2019.2.18

原文地址:https://www.cnblogs.com/butterflydew/p/10397591.html