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. Transaction 事务简单详解

    Transaction 也就是所谓的事务了,通俗理解就是一件事情.从小,父母就教育我们,做事情要有始有终,不能半途而废. 事务也是这样,不能做一半就不做了,要么做完,要么就不做.也就是说,事务必须是一 ...

  2. beta冲刺1-咸鱼

    前言:这篇算是开始补之前的开端,毕竟beta阶段我们从前面开始就有在陆续做了. 今天的工作: 接收了新成员*1,然后几个人聚了一下,并且讨论了一下目前遇到的问题,以及目前需要处理的问题. 目前遇到的问 ...

  3. Alpha冲刺No.8

    一.站立式会议 解决真实手机中出现的各种问题 细化界面设计 数据库上传与获取日拍 二.项目实际进展 能够上传和获取日拍信息 界面设计微调 三.燃尽图 四.团队合照 五.总结 白天金工实习,晚上才有时间 ...

  4. APP的案例分析-美团外卖

    大一才开始用软件订外卖了,很方便  ,上手快只要注册个账号登陆即可,支付时自动跳转到其他支付应用.严重的bug也没有,只有之前一段时间通过首单可以刷优惠,之后也修复了. 身边的同学也很多都在用.方便省 ...

  5. 用python实现简单购物车功能

    all_asset = 0 i1 = input("请输入总资产:") all_asset = int(i1) goods = [ {'name':'电脑','price':199 ...

  6. Flask Session 详解

    会话session ,允许你在不同请求 之间储存信息.这个对象相当于用密钥签名加密的 cookie ,即用户可以查看你的 cookie ,但是如果没有密钥就无法修改它. from flask impo ...

  7. Hibernate之深入Hibernate的映射文件

    这周周末 要把hibernate的映射文件搞定 .. 1.映射文件的主结构 主要结构  :根元素为<hibernate-mapping ></hibernate-mapping> ...

  8. 构建微服务开发环境3————Java应用的优秀管理工具Maven的下载安装及配置

    [内容指引] 下载安装包: MacOS下Maven的安装及配置: Windows下Maven的安装及配置. 一.下载安装包 进入Maven的官方下载地址:http://maven.apache.org ...

  9. python 之 列表list && 元组tuple

    目录: 列表 列表基本操作 列表的操作符 列表的函数和方法 元组 介绍: 列表是一种可变的有序集合,可以进行访问.添加和删除操作. 元组是一种不可变的有序集合,可以访问. 1.列表的基本操作 创建列表 ...

  10. Web Api 使用模型验证

    public class Person { public int Id { get; set; } [Required(ErrorMessage = "姓名不能为空啊啊啊!")] ...