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年,佳媛姐姐喜欢上了数字序列 ...
随机推荐
- 中国电信物联网平台入门学习笔记2: DOME程序分析
"墨子号NB-IOT开发板"提供的dome: 程序只要分为延时,定时器,串口通讯…… 工程文件在:…\STM32L1xx_StdPeriph_Lib_V1.3.1\Project\ ...
- Cplex: MIP Control Callback Methods
*本文主要记录和分享学习到的知识,算不上原创 *参考文献见链接 本文主要归纳了Cplex的Control callback常用的方法. 目录 NodeCallback SolveCallback Us ...
- Linux学习-循环执行的例行性工作排程
循环执行的例行性工作排程则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的例行性工作,因此这个系统服务是默认启动的. 另外, 由于使用者自己也可以进行例行性工 ...
- 虚拟机上的Linux学习
title: 虚拟机上的Linux学习 date: 2018-08-08 15:48:28 updated: tags: [Linux,学习笔记] description: keywords: com ...
- 聊聊、Nginx 参数合法性
我们接着上篇文章来讲讲 ngx_get_options 函数. 这个函数就在 nginx.c 文件中,我们来看看. 参数 argc,argv 我们在前面的文章中都已经提到了,在这里我们看 ngx_ge ...
- [git 学习篇] git文件版本回退再学习
需求; 准备把readme.txt回退到上一个版本,也就是“add distributed”的那个版本 首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交3 ...
- EOJ Monthly 2018.1
985月赛,当时鸽了,现在想补一补 A. 石头剪刀布的套路 Time limit per test: 1.0 seconds Memory limit: 256 megabytes 现在有一种石头剪刀 ...
- java中equals和hashCode方法随笔二
前几天看了篇关于java中equals和hashCode方法的解析 1.Object类中的equals方法和hashCode方法. Object类中的equals和hashCode方法简单明了,所有的 ...
- javascript基础1 语法 点击事件 超链接带点击事件
javascript ----------------------------------------------------------------------------------------- ...
- Linux Shell系列教程之(八)Shell printf命令详解
本文是Linux Shell系列教程的第(八)篇,更多shell教程请看:Linux Shell系列教程 在上一篇:Linux Shell系列教程之(七)Shell输出这篇文章中,已经对Shell p ...