Description

A国有N座城市,依次标为1到N。同时,在这N座城市间有M条单向道路,每条道路的长度是一个正整数。现在,A国 交通部指定了一条从城市1到城市N的路径,并且保证这条路径的长度是所有从城市1到城市N的路径中最短的。不幸的是,因为从城市1到城市N旅行的人越来越 多,这条由交通部指定的路径经常发生堵塞。现在A国想知道,这条路径中的任意一条道路无法通行时,由城市1到N的最短路径长度是多少。

Input

输入文件第一行是三个用空格分开的正整数N、M和L,分别表示城市数目、单向道路数目和交通部指定 的最短路径包含多少条道路。按下来M行,每行三个用空格分开的整数a、b和c,表示存在一条由城市a到城市b的长度为c的单向道路。这M行的行号也是对应 道路的编号,即其中第1行对应的道路编号为1,第2行对应的道路编号为2,...,第M行对应的道路编号为M。最后一行为L个用空格分开的整数 sp(1)...,,sp(L),依次表示从城市1到城市N的由交通部指定的最短路径上的道路的编号。

Output

输出文件包含L行,每行为一个整数,第i行(i=1,2...,,L)的整数表示删去编号为sp(i)的道路后从城市1到城市N的最短路径长度。如果去掉后没有从城市1到城市N的路径,则输出一1。

Sample Input

4 5 2
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
1 5

Sample Output

6
6

Hint

100%的数据满足2<N<100000,1<M<200000。所用道路长度大于0小于10000。

题目大意

给出一个N个节点,M条边的有向图。给出一条1到N的最短路,问最短路上任意一条边断掉,此时的最短路是多少。

题解

考虑不可能每次删掉当前边之后再跑一遍最短路,那必须想办法优化删边和求得最短路过程。

我们将最短路上的点从小到大标号。

考虑删边之后,当前的从$1$到$N$的最短路只能是从$1$出发,在最短路径上走一段,再走一段非最短路,最后回到最短路径上。那么如果强制不走当前边,在跑最短路的过程中,只要发现走到了一个最短路径上的点上时(这个点肯定是最短路上标号更大的点),既然在最短路上,就不必要继续松弛了,显然$SPFA$求出的$dis$值+该点到终点的距离$last$就是一个可行的解,更新$ans$。

其实上述过程得到的解还是没有充分利用的。我们会发现,以后的$SPFA$搜到解会和当前这次$SPFA$得到的解重复。这些重复的解的共同特点就是终止的节点的标号都大于这两个的标号。(想象一下,既然第一次搜到了一个标号很大的解,显然它是没有在这个点之前走上最短路的,就是它同时也绕过了后来的一条强制不走的边),所以这个解是可以继续用的。

用堆保存一下走到哪个在最短路上的点导致的更新$ans$的话,就可以在以后反复调用,保证全局最优了。注意每次跑$SPFA$无需清空$dis$,因为最短路从左往右做的时候,$dis$显然递减(想一想最短路的松弛操作),但是到达最短路上的点的标记必须清空。

玄学的时间复杂度...也能过...人生处处是惊喜...难道不是吗?

$SPFA$的时候不要用$STL$中的$queue$,$n$次拓展慢的吓人<代码中沿用,简洁一些(其实我懒,不想改)>。

 #include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<string>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
#define RE register
#define IL inline
using namespace std;
const int N=;
const int M=; IL int Read(); int n,m,l,sp[N+];
int last[N+],id[N+];
struct Link
{
int from,to,cost;
}lin[M+];
struct tt
{
int to,next,cost,id;
}edge[M+];
int path[N+],top;
IL void Add(int u,int v,int c,int id); struct node
{
int u,dis;
bool operator < (const node &b)
const{
return dis>b.dis;
}
};
priority_queue<node>Q; int dis[N+];
bool vis[N+];
IL void SPFA(int donot); int main()
{
n=Read();m=Read();l=Read();
for (RE int i=;i<=m;i++)
{
lin[i].from=Read();lin[i].to=Read();lin[i].cost=Read();
Add(lin[i].from,lin[i].to,lin[i].cost,i);
}
id[]=;
for (RE int i=;i<=l;i++) sp[i]=Read(),id[lin[sp[i]].to]=id[lin[sp[i]].from]+;
for (RE int i=l;i;i--) last[lin[sp[i]].from]=last[lin[sp[i]].to]+lin[sp[i]].cost;
memset(dis,/,sizeof(dis));dis[]=;
for (RE int i=;i<=l;i++)
{
if (i>) dis[lin[sp[i-]].to]=dis[lin[sp[i-]].from]+lin[sp[i-]].cost;
SPFA(sp[i]);
while (!Q.empty()&&id[lin[sp[i]].from]>=id[Q.top().u]) Q.pop();
printf("%d\n",Q.empty() ? -:Q.top().dis);
}
return ;
} IL void SPFA(int donot)
{
queue<int>q;
while (!q.empty()) q.pop();
q.push(lin[donot].from);
memset(vis,,sizeof(vis));
while (!q.empty())
{
for (RE int i=path[q.front()];i;i=edge[i].next) if (edge[i].id!=donot)
{
if (dis[edge[i].to]>dis[q.front()]+edge[i].cost)
{
dis[edge[i].to]=dis[q.front()]+edge[i].cost;
if (id[edge[i].to]) Q.push((node){edge[i].to,dis[edge[i].to]+last[edge[i].to]});
else if (!vis[edge[i].to])
{
vis[edge[i].to]=;
q.push(edge[i].to);
}
}
}
vis[q.front()]=;
q.pop();
}
}
IL void Add(int u,int v,int c,int id)
{
edge[++top].to=v;
edge[top].cost=c;
edge[top].id=id;
edge[top].next=path[u];
path[u]=top;
}
IL int Read()
{
char c=getchar();
int sum=;
while (c<''||c>'') c=getchar();
while (c>=''&&c<='') sum=sum*+c-'',c=getchar();
return sum;
}

[HNOI 2014]道路堵塞的更多相关文章

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

    [HNOI2014]道路堵塞 题意 给一个有向图并给出一个这个图的一个\(1\sim n\)最短路,求删去这条最短路上任何一条边后的最短路. 又事SPFA玄学... 有个结论,新的最短路一定是\(1\ ...

  2. HNOI 2014

    D1T1:画框 frame 题意:给你两个n阶正整数方阵,请你求最大的\( \sum_{i = 1}^{n} A_{i, p_i}\times \sum_{i = 1}^{n} B_{i, p_i}  ...

  3. 动态删边SPFA: [HNOI2014]道路堵塞

    [HNOI2014]道路堵塞 题目描述 $A$ 国有 $N$座城市,依次标为$1$到$N$.同时,在这$N$座城市间有$M$条单向道路,每条道路的长度是一个正整数.现在,$A$国交通部指定了一条从城市 ...

  4. HNOI 2014 米特运输(图论)

    HNOI 2014 米特运输 题目大意 给一棵树,每个点有自己的权值,要求更改一些点的权值,使得整棵树满足两个条件: 同一个父亲的所有子节点权值相同 父节点的取值为所有子节点的和 答案输出最少要更改的 ...

  5. BZOJ 3575 道路堵塞

    Description A国有N座城市,依次标为1到N.同时,在这N座城市间有M条单向道路,每条道路的长度是一个正整数.现在,A国交通部指定了一条从城市1到城市N的路径,并且保证这条路径的长度是所有从 ...

  6. bzoj 3575: [Hnoi2014]道路堵塞

    Description A 国有N座城市,依次标为1到N.同时,在这N座城市间有M条单向道路,每条道路的长度是一个正整数.现在,A国交通部指定了一条从城市1到城市N的路径, 并且保证这条路径的长度是所 ...

  7. [HNOI2014]道路堵塞

    题目描述 A国有N座城市,依次标为1到N.同时,在这N座城市间有M条单向道路,每条道路的长度是一个正整数.现在,A国交通部指定了一条从城市1到城市N的路径,并且保证这条路径的长度是所有从城市1到城市N ...

  8. 数据结构(虚树,动态规划):HNOI 2014 世界树

    Hnoi2014 世界树 Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平 ...

  9. [HNOI/AHOI2018]道路

    Description: W 国的交通呈一棵树的形状.W 国一共有\(n - 1\)个城市和\(n\)个乡村,其中城市从\(1\)到\(n - 1\) 编号,乡村从\(1\)到\(n\)编号,且\(1 ...

随机推荐

  1. JavaScript(第二十三天)【事件入门】

    JavaScript事件是由访问Web页面的用户引起的一系列操作,例如:用户点击.当用户执行某些操作的时候,再去执行一系列代码.   一.事件介绍 事件一般是用于浏览器和用户操作进行交互.最早是IE和 ...

  2. Alpha冲刺——Day1

    一.合照 二.项目燃尽图 三.项目进展 1.界面设计:图形界面部分完成 2.数据库设计:数据库设计基本完成 3.搭建基本服务器框架 github链接 四.明日规划 1.继续完成剩下的图形界面 2.An ...

  3. 第四次团队作业:社团申请App

    概要: 基于上次软件设计本着界面简洁.易于使用的初衷,进行功能的实现,代码位置:https://github.com/LinZezhong/testDemo 第一部分:软件的使用 注册: 登录: 主界 ...

  4. 2018c语言第1次作业

    6-1 计算两数的和与差 1.设计思路 (1)主要描述题目算法 第一步:把两个数的加减法分别赋给psum和pdiff. 第二步:通过psum和pdiff的地址把值传回主函数. (2)流程图.(无) 2 ...

  5. JAVA线程概念

    一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在 ...

  6. itchat 微信的使用

    #coding=utf8 import itchat # 自动回复 # 封装好的装饰器,当接收到的消息是Text,即文字消息 @itchat.msg_register('Text') def text ...

  7. JAVA中if多分支和switch的优劣性。

    Switch多分支语句switch语句是多分支选择语句.常用来根据表达式的值选择要执行的语句.例如,在某程序中,要求将输入的或是获取的用0-6代表的星期,转换为用中文表示的星期.该需求通过伪代码描述的 ...

  8. 【iOS】swift-通过JS获取webView的高度

     let webHeightStr = webView.stringByEvaluatingJavaScriptFromString("document.body.scrollHeight& ...

  9. Raid5两块硬盘掉线可以恢复数据吗_raid数据恢复案例分享

    本案例中发生故障的存储类型是HP P2000,虚拟化平台为vmware exsi,共有10块硬盘组成raid5(硬盘容量为1t,其中6号盘是热备盘),由于某些故障导致阵列中两块硬盘亮黄灯掉线,硬盘无法 ...

  10. __all__

    相信很多人第一次见到这个__all__都很好奇,他有什么作用 那他到底有什么作用呢? 先上代码 from scrapy.utils.reqser import request_to_dict, req ...