对不起对不起,辣鸡蒟蒻又来用核弹打蚊子了

完全ignore了题目给出的最短路,手工搞出一个最短路,发现对答案没什么影响

所以干脆转化为经典问题:每次询问删掉一条边后的最短路

如果删掉的是非最短路边,那么显然毫无影响

如果删掉的是最短路边,那么我们倒过来,考虑这个时候每条非最短路边的贡献。对于一条非最短路边 \((u,v)\) ,我们很容易得到一定包含它的最短路一定是满足 \(1 \to x \to u \to v \to y \to n\) 这样的结构,其中 \(x,y\) 都在选定的最短路上,那么只要删除的是最短路上 \(x \sim y\) 之间的边,这个贡献就是存在的。

考虑如何求出对 \((u,v)\) 的 \(x,y\) ,跑完最短路后搞出最短路径树,那么最短路显然是最短路径树的一条链。对这条链上任意一个点 \(p\) ,对它所有不在链上的儿子 \(q\) ,我们将每一个 \(q\) 的子树都打上 \(p\) 标记,表示从 \(1\) 到这些点的最短路在 \(p\) 点与选定的 \(1 \sim n\) 最短路分开

因此我们维护删掉最短路上每条边时的答案,这是一个序列。枚举每条非最短路边去计算它的贡献与贡献范围,贡献范围内的每个位置对它的贡献值取Min,线段树标记永久化维护即可。

#include <bits/stdc++.h>
using namespace std; const int N = 400005; int cnt = 0; struct item {
int v,w,id;
}; struct graph {
vector <item> g[N];
vector <int> tree[N];
int d[N],v[N],c[N],fa[N],fid[N]; void make(int t1,int t2,int t3,int t4) {
g[t1].push_back((item) {
t2,t3,t4
});
} void sp(int v0,int n) {
memset(d,0x3f,sizeof d);
memset(v,0x00,sizeof v);
priority_queue <pair<int,int> > q;
d[v0]=0;
q.push(make_pair(0,v0));
while(!q.empty()) {
pair<int,int> p=q.top();
int dis=-p.first, pos=p.second;
q.pop();
v[pos]=1;
for(int i=0;i<g[pos].size();i++) {
int x=g[pos][i].v,y=g[pos][i].w,z=g[pos][i].id;
if(d[x]>d[pos]+y) {
d[x]=d[pos]+y;
fa[x]=pos;
fid[x]=z;
if(!v[x]) q.push(make_pair(-d[x],x));
}
}
}
for(int i=1; i<=n; i++) {
if(fa[i])
tree[fa[i]].push_back(i);
c[i]=i;
}
} void dfs(int p,int x) {
c[p]=x;
for(int i=0; i<tree[p].size(); i++) {
dfs(tree[p][i],x);
}
} void gen(int s,int t) {
for(int p=t,q; q=fa[p]; p=q) {
for(int i=0; i<tree[q].size(); i++) {
if(tree[q][i]!=p) {
dfs(tree[q][i],q);
}
}
}
} } gs,gt; struct edge {
int u,v,w;
}; edge e[N];
int n,m,q,t1,t2,t3,t4,use[N],sid[N]; vector <int> sp; namespace seg {
int a[N<<2];
void reset() {
memset(a,0x3f,sizeof a);
}
void modify(int p,int l,int r,int ql,int qr,int x) {
if(l>qr||r<ql)
return;
if(l>=ql && r<=qr) {
a[p]=min(a[p],x);
} else {
modify(p*2,l,(l+r)/2,ql,qr,x);
modify(p*2+1,(l+r)/2+1,r,ql,qr,x);
}
}
int query(int p,int l,int r,int pos) {
if(l==r) {
return a[p];
} else {
if(pos<=(l+r)/2) {
return min(query(p*2,l,(l+r)/2,pos), a[p]);
} else {
return min(query(p*2+1,(l+r)/2+1,r,pos), a[p]);
}
}
}
} // namespace seg int chk(int x)
{
if(x>=0x3f3f3f3f) return -1;
else return x;
} signed main() {
seg::reset(); scanf("%d%d%d",&n,&m,&q);
for(int i=1; i<=m; i++) {
scanf("%d%d%d",&t1,&t2,&t3);
if(t2==1) t2=t1;
if(t1==n) t1=t2;
e[i] = (edge) {
t1,t2,t3
};
gs.make(t1,t2,t3,i);
gt.make(t2,t1,t3,i);
} gs.sp(1,n);
gt.sp(n,n);
gs.gen(1,n);
gt.gen(n,1); int ind = 0;
for(int i=1; gt.fa[i]; i=gt.fa[i]) {
sp.push_back(gt.fid[i]);
use[gt.fid[i]]=++ind;
}
sid[1]=0;
for(int i=0; i<sp.size(); i++) {
sid[e[sp[i]].v]=i+1;
}
int len=sp.size();
for(int i=1; i<=m; i++) {
if(use[i]==0) {
int u=e[i].u, v=e[i].v, w=e[i].w;
seg::modify(1,1,len,sid[gs.c[u]]+1,sid[gt.c[v]],gs.d[u]+gt.d[v]+w);
}
} for(int i=1; i<=q; i++) {
scanf("%d",&t1);
if(use[t1])
printf("%d\n",chk(seg::query(1,1,len,use[t1])));
else
printf("%d\n",chk(gs.d[n]));
}
}

[HNOI2014] 道路堵塞 - 最短路,线段树的更多相关文章

  1. BZOJ.3575.[HNOI2014]道路堵塞(最短路 动态SPFA)

    题目链接 \(Description\) 给你一张有向图及一条\(1\)到\(n\)的最短路.对这条最短路上的每条边,求删掉这条边后\(1\)到\(n\)的最短路是多少. \(Solution\) 枚 ...

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

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

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

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

  4. BZOJ1018[SHOI2008]堵塞的交通——线段树

    题目描述 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总 ...

  5. Luogu P4246 [SHOI2008]堵塞的交通(线段树+模拟)

    P4246 [SHOI2008]堵塞的交通 题意 题目描述 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个\(2\)行\(C\)列的矩形 ...

  6. HDU5669 Road 分层最短路+线段树建图

    分析:(官方题解) 首先考虑暴力,显然可以直接每次O(n^2) ​的连边,最后跑一次分层图最短路就行了. 然后我们考虑优化一下这个连边的过程 ,因为都是区间上的操作,所以能够很明显的想到利用线段树来维 ...

  7. [TJOI2012]桥(最短路+线段树)

    有n个岛屿, m座桥,每座桥连通两座岛屿,桥上会有一些敌人,玩家只有消灭了桥上的敌人才能通过,与此同时桥上的敌人会对玩家造成一定伤害.而且会有一个大Boss镇守一座桥,以玩家目前的能力,是不可能通过的 ...

  8. BZOJ.1018.[SHOI2008]堵塞的交通(线段树维护连通性)

    题目链接 只有两行,可能的路径数不多,考虑用线段树维护各种路径的连通性. 每个节点记录luru(left_up->right_up),lurd,ldru,ldrd,luld,rurd,表示这个区 ...

  9. [BZOJ4699]树上的最短路(最短路+线段树)

    https://www.cnblogs.com/Gloid/p/10273902.html 这篇文章已经从头到尾讲的非常清楚了,几乎没有什么需要补充的内容. 首先$O(n\log^2 n)$的做法比较 ...

随机推荐

  1. 牛客网剑指offer第13题——调整数组顺序使得奇数位于偶数前面

    题目来源:剑指offer 题目: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变 ...

  2. 9个常用的正则表达式-sunziren

    正数字:/^[1-9]{1}[0-9]*$|^0{1}\.{1}[0-9]+$|^[1-9]{1}[0-9]*\.{1}[0-9]+$/ 用户名:/^[a-z0-9_-]{3,16}$/ 密码:/^[ ...

  3. python数据类型(总结篇)

    世界上最容易的事是坚持,最难的事也是坚持.开通博客园已两月有余,但实际上笔者本人的活跃度非常低,痛定思痛,自己选的路含泪也要走下去,继续坚持! 本文承接前几个月的python数据类型系列,完成对字典与 ...

  4. 论文阅读笔记(十六)【AAAI2018】:Region-Based Quality Estimation Network for Large-Scale Person Re-Identification

    Introduction (1)Motivation: 当前的行人重识别方法都只能在标准的数据集上取得好的效果,但当行人被遮挡或者肢体移动时,往往效果不佳. (2)Contribution: ① 提出 ...

  5. 转:Laravel 项目开发规范

    文件介绍很好 值得细细看看 https://www.jianshu.com/p/e464a35e5ed2 https://learnku.com/docs/laravel-specification/ ...

  6. 剑指offer-面试题29-顺时针打印矩阵-矩阵

    /* 题目: 输入一个矩阵,按照从外到内顺时针的顺序依次打印每一个数字. */ /* 思路: 1.将打印矩阵看作是打印一个个从外向内的环. 2.每一个环都有一个起始节点,起始节点的坐标*2小于行数和列 ...

  7. 【巨杉数据库SequoiaDB】省级农信国产分布式数据库应用实践

    本文转载自<金融电子化> 原文链接:https://mp.weixin.qq.com/s/WGG91Rv9QTBHPsNVPG8Z5g 随着移动互联网的迅猛发展,分布式架构在互联网IT技术 ...

  8. PAT (Basic Level) Practice (中文)1029 旧键盘 (20 分)

    旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现.现在给出应该输入的一段文字.以及实际被输入的文字,请你列出肯定坏掉的那些键. 输入格式: 输入在 2 行中分别给出应该输入的文字.以及 ...

  9. Wannafly Winter Camp 2020 Day 5G Cryptographically Secure Pseudorandom Number Generator - 分块

    多组数据,给定质数 \(p\) ,求所有 \(x\) 使得 \(f(x)=\min_{k=2}^x f(k)\) ,其中 \(f(x)=x^{-1}\) 所有 \(p\) 在 \([1,10^9]\) ...

  10. PP: Taking the human out of the loop: A review of bayesian optimization

    Problem: Design problem parameters consist of the search space of your model. Scientists design expe ...