BZOJ 3575 道路堵塞
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
1 2 1
2 3 1
4 6 1
2 5 2
5 4 3
1 2 3 4
Sample Output
7
7
-1
HINT
100%的数据满足2<N<100000,1<M<200000。所用道路长度大于0小于10000。
这题我用的ydc的做法。。。但是不得不承认他还是太屌了。。。QAQ
首先很容易想到即使去掉一条边之后,最短路依然是pre[a]+suf[b]+dis(a,b),其中a,b均为最短路上的点,pre指a到起点的最短路距离,b为b到终点的最短路距离,dis(a,b)为a到b的距离(不走最短路上的边)。。。
然后我就想到这里了。。。
之后就是ydc神奇做法。首先肯定还是枚举删去的边,然后从这条边的出发点开始跑spfa,不走删掉的边(注意,不要取清空dis数组,因为每个点的dis肯定是单调递减的,不然必然会TLE)。从该点跑到另一个最短路上的点p(p必须在所删的边之后),然后把整条路径的长度和p一起加入平衡树中。出来平衡树中取出长度最小的边,若其做对应的p点(最短路)并没有在所删的边之后,该边删除。若平衡树为空,则输出-1。
不得不说这个做法很漂亮,它利用到了枚举边的单调性,反正我肯定想不到。。。。
如果实在是不懂的话,看代码,代码应该很好理解。
#include<set>
#include<queue>
#include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std; #define maxn (200010)
int side[maxn],toit[maxn],next[maxn],dis[maxn],pos[maxn],occ[maxn],stack[maxn];
int pre[maxn],suf[maxn],len[maxn],n,m,l,id,cnt,p[maxn],edge[maxn],val[maxn];
bool ban[maxn],in[maxn];
struct node
{
int to,val;
friend inline bool operator <(const node &a,const node &b)
{
if (a.val != b.val) return a.val < b.val;
else return pos[a.to] < pos[b.to];
}
};
multiset <node> MS; inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} inline void add(int a,int b,int c)
{
next[++cnt] = side[a]; side[a] = cnt;
toit[cnt] = b; len[cnt] = c;
} inline void spfa(int d,int source,int lim)
{
queue <int> team; int top = ;
team.push(source); dis[source] = d; ++id;
while (!team.empty())
{
int now = team.front(); team.pop();
for (int i = side[now];i;i = next[i])
{
if (ban[i]) continue;
if (pos[toit[i]] >= lim)
{
if (occ[toit[i]] != id)
occ[toit[i]] = id,stack[++top] = toit[i],val[toit[i]] = dis[now]+len[i]+suf[pos[toit[i]]];
else val[toit[i]] = min(val[toit[i]],dis[now]+len[i]+suf[pos[toit[i]]]);
}
else if (dis[toit[i]] > dis[now]+len[i])
{
dis[toit[i]] = dis[now] + len[i];
if (!in[toit[i]]) in[toit[i]] = true,team.push(toit[i]);
}
}
in[now] = false;
}
for (int i = ;i <= top;++i) MS.insert((node) {stack[i],val[stack[i]]});
} inline void work()
{
pos[] = p[] = ;
for (int i = ;i <= l;++i)
edge[i] = read(),pos[toit[edge[i]]] = i+,p[i+] = toit[edge[i]];
for (int i = ;i <= l;++i) pre[i] = pre[i-]+len[edge[i]];
for (int i = l;i;--i) suf[i] = suf[i+]+len[edge[i]];
memset(dis,0x7,*(n+)); dis[] = ;
for (int i = ;i <= l;++i)
{
ban[edge[i]] = true; spfa(pre[i-],p[i],i+); ban[edge[i]] = false;
while (!MS.empty()&&pos[MS.begin()->to]<=i) MS.erase(MS.begin());
if (MS.empty()) puts("-1");
else printf("%d\n",MS.begin()->val);
}
} int main()
{
freopen("3575.in","r",stdin);
freopen("3575.out","w",stdout);
n = read(),m = read(),l = read(); int a,b,c;
while (m--) a = read(),b = read(),c = read(),add(a,b,c);
work();
fclose(stdin); fclose(stdout);
return ;
}
BZOJ 3575 道路堵塞的更多相关文章
- 洛谷 [HNOI2014]道路堵塞 解题报告
[HNOI2014]道路堵塞 题意 给一个有向图并给出一个这个图的一个\(1\sim n\)最短路,求删去这条最短路上任何一条边后的最短路. 又事SPFA玄学... 有个结论,新的最短路一定是\(1\ ...
- 动态删边SPFA: [HNOI2014]道路堵塞
[HNOI2014]道路堵塞 题目描述 $A$ 国有 $N$座城市,依次标为$1$到$N$.同时,在这$N$座城市间有$M$条单向道路,每条道路的长度是一个正整数.现在,$A$国交通部指定了一条从城市 ...
- BZOJ 2200 道路与航线(图论)
BZOJ 2200 道路与航线 题目大意 有两种路,一种没负数,一种没环,求单源最短路. solution 存在负边权Dij一定不能用嘛,显然不是 根据题意能看出来是tarjan,将双向边缩点,得到的 ...
- bzoj 3575: [Hnoi2014]道路堵塞
Description A 国有N座城市,依次标为1到N.同时,在这N座城市间有M条单向道路,每条道路的长度是一个正整数.现在,A国交通部指定了一条从城市1到城市N的路径, 并且保证这条路径的长度是所 ...
- 【BZOJ】3575: [Hnoi2014]道路堵塞
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3575 大概的做法是,按照顺序枚举每一条要删去的边,(假设当前点为$u$,在最短路径上的下一 ...
- BZOJ.3575.[HNOI2014]道路堵塞(最短路 动态SPFA)
题目链接 \(Description\) 给你一张有向图及一条\(1\)到\(n\)的最短路.对这条最短路上的每条边,求删掉这条边后\(1\)到\(n\)的最短路是多少. \(Solution\) 枚 ...
- 数据结构(线段树):BZOJ 1018: [SHOI2008]堵塞的交通traffic
1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 2638 Solved: 864 Descri ...
- BZOJ 1018 [SHOI2008]堵塞的交通traffic
1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 2247 Solved: 706[Submit ...
- BZOJ 1018: [SHOI2008]堵塞的交通traffic [线段树 区间信息]
1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 3064 Solved: 1027[Submi ...
随机推荐
- Java开发中文件读取方式总结
JAVA开发中,免不了要读文件操作,读取文件,首先就需要获取文件的路径. 路径分为绝对路径和相对路径. 在文件系统中,绝对路径都是以盘符开始的,例如C:\abc\1.txt. 什么是相对路径呢?相对路 ...
- Google搜索解析
Google搜索解析 是一款相似于Google趋势的SEO 在 线keyword工具,其官方提出的口号是“看看全世界的人们都在搜索些什么”.利用Google搜索解析,能够比較特定区域.类别.时间范围以 ...
- mysql --batch --skip-column-name --execute 使用
mysql -h 127.0.0.1 -P 3306 -u root -p -D test --batch --skip-column-name --execute="select * fr ...
- linux device driver —— 环形缓冲区的实现
还是没有接触到怎么控制硬件,但是在书里看到了一个挺巧妙的环形缓冲区实现. 此环形缓冲区实际为一个大小为bufsize的一维数组,有一个rp的读指针,一个wp的写指针. 在数据满时写进程会等待读进程读取 ...
- Java基础知识强化之集合框架笔记23:ArrayList的实现原理
1. ArrayList的实现原理: 这个可以直接参考网友的博客:http://www.cnblogs.com/ITtangtang/p/3948555.html
- json、xml ---- 数据格式生成类
自己写的一个生成json/xml 格式数据的类,可用于api数据传输: <?php class Response{ /** *生成指定数据格式 *@param intval $code 状态码 ...
- sql server查询时候注意的基本优化常识
1.在Where条件中尽量不要在=号左边进行函数.运算符.或表达式计算 2.在Where中尽量避免出现!=或<>操作符: 3.在Where中尽量避免对字段进行null值判定: 4.使用Li ...
- C# gridview分頁導出excel
#region 导出Excel方法 //导出到Excel按钮 protected void btnExport_Click(object sender, EventArgs e) { Export(& ...
- Netbeans IDE配置
- shell脚本学习之if..else用法
一 简介 1 字符串判断 str1 = str2 当两个串有相同内容.长度时为真 str1 != str2 当串str1和str2不等时为真 -n str1 当串的长度大于0时为真(串非空) - ...