Wannafly挑战赛2 D.Delete(拓扑排序 + dij预处理 + 线段树维护最小值)
题目链接 D.Delete
考虑到原图是个DAG,于是我们可以求出每个点的拓扑序。
然后预处理出起点到每个点的最短路$ds[u]$,
和所有边反向之后从终点出发到每个点的最短路$dt[u]$。
令点$u$的拓扑序为$a(u)$。
对于特定的一条边$(u, v, w)$,相当于给所有拓扑序为$[a(u) + 1, a[v] - 1]$的点贡献了一条总长度为$ds[u] + dt[v] + w$的路径。
我们在询问点$u$的时候找到对$u$点贡献的所有路径中长度最小的即可。
特别地,当$s$无法到达$u$或$u$无法到达t时,输出原图从$s$到$t$的最短路即可。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define lson i << 1, L, mid
#define rson i << 1 | 1, mid + 1, R typedef long long LL; const int N = 1e5 + 10;
const LL INF = 1e18; int n, m, s, t, q;
LL ans;
LL ds[N], dt[N];
LL mi[N << 2]; struct node{
int u;
LL w;
friend bool operator < (const node &a, const node &b){
return a.w > b.w;
}
}; vector <node> v[N], g[N];
int a[N], deg[N]; void dij(int s, LL dis[], vector <node> v[]){
priority_queue <node> q;
static bool vis[N];
rep(i, 1, n) dis[i] = 1e18, vis[i] = false;
q.push({s, 0});
dis[s] = 0;
while (!q.empty()){
int u = q.top().u; q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (auto edge : v[u]) if (dis[u] + edge.w < dis[edge.u]){
dis[edge.u] = dis[u] + edge.w;
q.push({edge.u, dis[edge.u]});
}
}
} void getdag(){
queue <int> q;
int cnt = 0;
rep(i, 1, n){
if (deg[i] == 0) a[i] = ++cnt, q.push(i);
} while (!q.empty()){
int x = q.front(); q.pop();
for (auto edge : v[x]){
--deg[edge.u];
if (deg[edge.u] == 0) a[edge.u] = ++cnt, q.push(edge.u);
}
}
} void build(int i, int L, int R){
mi[i] = INF;
if (L == R) return;
int mid = (L + R) >> 1;
build(lson);
build(rson);
} void update(int i, int L, int R, int l, int r, LL val){
if (l <= L && R <= r){
mi[i] = min(mi[i], val);
return;
} int mid = (L + R) >> 1;
if (l <= mid) update(lson, l, r, val);
if (r > mid) update(rson, l, r, val);
} void query(int i, int L, int R, int x, LL &ans){
ans = min(ans, mi[i]);
if (L == R) return;
int mid = (L + R) >> 1;
if (x <= mid) query(lson, x, ans);
else query(rson, x, ans);
} int main(){ scanf("%d%d%d%d", &n, &m, &s, &t);
rep(i, 1, m){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
v[x].push_back({y, z});
g[y].push_back({x, z});
++deg[y];
} getdag();
dij(s, ds, v);
dij(t, dt, g); build(1, 1, n);
rep(i, 1, n){
for (auto edge : v[i]){
if (a[i] + 1 < a[edge.u] && ds[i] != INF && dt[edge.u] != INF){
update(1, 1, n, a[i] + 1, a[edge.u] - 1, ds[i] + dt[edge.u] + edge.w);
}
}
} scanf("%d", &q);
while (q--){
int x;
scanf("%d", &x);
ans = INF;
if (ds[x] == INF || dt[x] == INF){
printf("%lld\n", dt[s]);
continue;
} query(1, 1, n, a[x], ans);
if (ans == INF) puts("-1");
else printf("%lld\n", ans);
} return 0;
}
Wannafly挑战赛2 D.Delete(拓扑排序 + dij预处理 + 线段树维护最小值)的更多相关文章
- Wannafly挑战赛2_D Delete(拓扑序+最短路+线段树)
Wannafly挑战赛2_D Delete Problem : 给定一张n个点,m条边的带权有向无环图,同时给定起点S和终点T,一共有q个询问,每次询问删掉某个点和所有与它相连的边之后S到T的最短路, ...
- 【拓扑排序】【线段树】Gym - 101102K - Topological Sort
Consider a directed graph G of N nodes and all edges (u→v) such that u < v. It is clear that this ...
- bzoj4383 [POI2015]Pustynia 拓扑排序+差分约束+线段树优化建图
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4383 题解 暴力的做法显然是把所有的条件拆分以后暴力建一条有向边表示小于关系. 因为不存在零环 ...
- Wannafly挑战赛10 D 小H的询问(线段树)
题目链接 Problem D 这个题类似 SPOJ GSS3 做过那个题之后其实就可以秒掉这题了. 考虑当前线段树维护的结点 在那道题的基础上,这个题要多维护几个东西,大概就是左端点的奇偶性,右端点 ...
- [luogu3573 POI2014] RAJ-Rally (拓扑排序 权值线段树)
传送门 Solution 在DAG中我们可以\(O(n)\)预处理\(Ds(u)\)表示从u表示以s为起点的最长路\(Dt(u)\)表示以u为终点的最长路,那么经过\((u,v)\)的最长路即为\(D ...
- [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)
解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...
- 【拓扑 字符串还原 + 线段树维护】奇洛金卡达(father)
奇洛金卡达(father) Description 阿良良木历将要迎来人生(不,是吸血鬼生涯)的第三次战斗——与身为人类的奇洛金卡达在直江津高中的操场solo,以取回Heartunderblade 的 ...
- 2018.08.01 BZOJ4552: [Tjoi2016&Heoi2016]排序(二分+线段树)
传送门 线段树简单题. 二分答案+线段树排序. 实际上就是二分答案mid" role="presentation" style="position: relat ...
- 【BZOJ4552】【HEOI2016】排序 [二分答案][线段树]
排序 Time Limit: 60 Sec Memory Limit: 256 MB[Submit][Status][Discuss] Description 在2016年,佳媛姐姐喜欢上了数字序列 ...
随机推荐
- jQuery将物体居中,并且转换显示和隐藏
今天来给大家贴一段代码,代码的作用就是利用jQuery将物体居中,并且转换显示和隐藏: 首先建立一个div标签并且写好css样式,具体如下 然后我想要的效果是当我点击了button这个按钮,test可 ...
- PHPExcel探索之旅
学习地址: https://www.imooc.com/video/8359 下载地址: https://packagist.org/packages/phpoffice/phpexcel 用comp ...
- java上传附件,批量下载附件(一)
上传附件代码:借助commons-fileupload-1.2.jar package com.str; import java.io.BufferedInputStream;import java. ...
- python-函数基础、函数参数
目录 函数的基础 什么是函数 为何用函数 如何调用函数 定义函数的三种形式 无参函数 有参函数 空函数 函数的返回值 什么是返回值 为什么要有返回值 函数的调用 函数参数的应用 形参和实参 位置参数 ...
- 让Python带你看一场唯美的横飘雪!
“北国风光,千里冰封,万里雪飘”,这句诗描写了一句美丽肃静的风光图,恰逢昨天笔者这边也下了一场比较大的雪,要不今天就用Python带大家也来领略一次美丽的雪景? 开发环境 版本:Python3.6 系 ...
- init_bootmem_node
初始化pg_data_t->bdtat结构体, /* * node_bootmem_map is a map pointer - the bits represent all physical ...
- STM32F407VET6之IAR之ewarm7.80.4工程建立(基于官方固件库1.6版本) 的工程文件目录
最后整理结构如下所示,├─cmsis│ startup_stm32f401xx.s│ startup_stm32f40xx.s│ startup_stm32f40_41xxx.s│ startup_s ...
- poj 3614 伪素数问题
题意:1.p不是素数 2.(a^p)%p=a 输出yes 不满足输出no 思路: 判断素数问题,直接暴力判断 bool is_prime(int n) { for(int i=2;i*i<= ...
- Linux学习-服务器硬件数据的收集
以系统内建 dmidecode 解析硬件配备 系统有个名为 dmidecode 的软件,它可以解析 CPU 型号.主板型号与内存相 关的型号等等~ [root@study ~]# dmidecode ...
- Linux对大容量硬盘分区
随着单块硬盘容量的增大和硬盘价格的下降,2TB的磁盘使用将很快会普及,由于传统的MBR方式存储分区表的方 式缺陷,将可能导致很多分区工具不能正确地读取大于2TB容量的硬盘而无法正常分区大容量硬盘.其实 ...