Wannafly挑战赛2_D Delete

Problem :

给定一张n个点,m条边的带权有向无环图,同时给定起点S和终点T,一共有q个询问,每次询问删掉某个点和所有与它相连的边之后S到T的最短路,询问之间互相独立(即删除操作在询问结束之后会立即撤销),如果删了那个点后不存在S到T的最短路,则输出-1。

n,q <= 10^5

Solution :

注意到题中所给的是DAG,首先可以找出图中结点的拓扑序。对于删除掉某个点之后,若仍存在一条从S到T的最短路,那么对应到拓扑序中,必然有一条边跨过了该点(即这条边的两个端点的拓扑序在这个点的两边)。故对于每条边(u, v, w), 对拓扑序(a[u], a[v])中的点提供了一条长度为ds[u]+dt[v]+w的最短路,用线段树来维护最小值。

注意特判若u->v不可能经过这个点,那么直接输出最短路。

#include <bits/stdc++.h>
using namespace std; #define endl "\n"
const long long INF = 1ll << 60;
const int N = 1e5 + 8;
struct edge
{
int v, w;
edge(int v = 0, int w = 0):v(v),w(w){}
};
vector <edge> vec[N], vec2[N];
long long ds[N], dt[N];
int a[N], deg[N];
int n, m, S, T; void init()
{
cin >> n >> m >> S >> T;
for (int i = 1; i <= n; ++i) vec[i].clear(), vec2[i].clear();
for (int i = 1; i <= m; ++i)
{
int u, v, w; cin >> u >> v >> w;
vec[u].push_back(edge(v, w));
vec2[v].push_back(edge(u, w));
deg[v]++;
}
}
void getDag()
{
static queue <int> Q;
int tot = 0;
for (int i = 1; i <= n; ++i)
{
if (deg[i] == 0)
{
a[i] = ++tot;
Q.push(i);
}
}
while (!Q.empty())
{
int u = Q.front(); Q.pop();
for (auto p : vec[u])
{
deg[p.v]--;
if (deg[p.v] == 0)
{
a[p.v] = ++tot;
Q.push(p.v);
}
}
}
}
struct node
{
int u;
long long w;
bool operator < (const node &b) const
{
return w > b.w;
}
};
void Dijkstra(int S, long long dis[], vector <edge> vec[])
{
static priority_queue<node> Q;
static bool vis[N];
for (int i = 1; i <= n; ++i) dis[i] = INF, vis[i] = 0;
Q.push((node){S, 0});
dis[S] = 0;
while (!Q.empty())
{
int u = Q.top().u; Q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (auto p : vec[u])
if (dis[u] + p.w < dis[p.v])
{
dis[p.v] = dis[u] + p.w;
Q.push((node{p.v, dis[p.v]}));
}
}
}
class SegmentTree
{
public:
long long tag[N << 2];
void build(int l, int r, int rt)
{
tag[rt] = INF;
if (l == r) return;
int m = l + r >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
}
void update(int L, int R, long long val, int l, int r, int rt)
{
// if (l == 1 && r == n) cout << L << " " << R << " " << val << endl;
if (L <= l && r <= R)
{
tag[rt] = min(tag[rt], val);
return;
}
int m = l + r >> 1;
if (L <= m) update(L, R, val, l, m, rt << 1);
if (m < R) update(L, R, val, m + 1, r, rt << 1 | 1);
}
void query(int x, int l, int r, int rt, long long &ans)
{
ans = min(ans, tag[rt]);
if (l == r) return;
int m = l + r >> 1;
if (x <= m) query(x, l, m, rt << 1, ans);
else query(x, m + 1, r, rt << 1 | 1, ans);
}
}ST;
void buildSeg()
{
ST.build(1, n, 1);
for (int u = 1; u <= n; ++u)
for (auto p : vec[u])
if (a[u] + 1 < a[p.v] && ds[u] != INF && dt[p.v] != INF)
{
// cout << u << " " << p.v << " " << a[u] << " " << a[p.v] << endl;
ST.update(a[u] + 1, a[p.v] - 1, ds[u] + dt[p.v] + p.w, 1, n, 1);
}
}
void solve()
{
int Q; cin >> Q;
for (; Q; --Q)
{
int u; cin >> u;
long long ans = INF;
if (ds[u] == INF || dt[u] == INF)
{
cout << dt[S] << endl;
continue;
}
ST.query(a[u], 1, n, 1, ans);
if (ans == INF) cout << -1 << endl; else cout << ans << endl;
}
}
int main()
{
cin.sync_with_stdio(0);
init();
getDag();
Dijkstra(S, ds, vec);
Dijkstra(T, dt, vec2);
buildSeg();
solve();
}

Wannafly挑战赛2_D Delete(拓扑序+最短路+线段树)的更多相关文章

  1. 【Wannafly挑战赛29F】最后之作(Trie树,动态规划,斜率优化)

    [Wannafly挑战赛29F]最后之作(Trie树,动态规划,斜率优化) 题面 牛客 题解 首先考虑怎么计算\([l,r]\)这个子串的不同的串的个数. 如果\(l=1\),我们构建\(Trie\) ...

  2. Codeforces Round #442 (Div. 2) E Danil and a Part-time Job (dfs序加上一个线段树区间修改查询)

    题意: 给出一个具有N个点的树,现在给出两种操作: 1.get x,表示询问以x作为根的子树中,1的个数. 2.pow x,表示将以x作为根的子树全部翻转(0变1,1变0). 思路:dfs序加上一个线 ...

  3. 【bzoj4771】七彩树 树链的并+STL-set+DFS序+可持久化线段树

    题目描述 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义 ...

  4. hdu5692【dfs序】【线段树】

    Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  5. Wannafly挑战赛2 D.Delete(拓扑排序 + dij预处理 + 线段树维护最小值)

    题目链接  D.Delete 考虑到原图是个DAG,于是我们可以求出每个点的拓扑序. 然后预处理出起点到每个点的最短路$ds[u]$, 和所有边反向之后从终点出发到每个点的最短路$dt[u]$. 令点 ...

  6. Wannafly挑战赛2D Delete (最短路好题)

    大意: 给定DAG, 给定点$S,T$, 每次询问给出点$x$, 求删除$x$后的$S->T$的最短路, 询问之间独立. 删除点$x$的最短路一定要经过一条边$(u,v)$, 满足$u$拓扑序在 ...

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

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

  8. BZOJ4400 TJOI2012桥(最短路+线段树)

    首先找出任意一条1-n的最短路径.显然删除的边只有在该最短路上才会对最短路长度产生影响. 不会证明地给出一个找不到反例的结论:删除一条边后,新图中一定有一条1-n的最短路径上存在一条边x->y, ...

  9. 【62测试】【状压dp】【dfs序】【线段树】

    第一题: 给出一个长度不超过100只包含'B'和'R'的字符串,将其无限重复下去. 比如,BBRB则会形成 BBRBBBRBBBRB 现在给出一个区间[l,r]询问该区间内有多少个字符'B'(区间下标 ...

随机推荐

  1. Mac OS OneDrive 无法同步.DS_Store文件 出错

    Mac OS OneDrive 无法同步.DS_Store文件 同步出错 解决方案: 第一步:打开 terminal 窗口,到本地同步的目录下: cd "/Users/gkjglobal/G ...

  2. Eclipse项目转Android Studio

    刚来某公司的时候,发现Android开发仍然还在使用Eclipse,编码无规范,渠道打包竟然手动,svn版本主干分支管理混乱,总之各种low... 对于有强迫症的我来说,属实不可忍.但无奈,新人一个, ...

  3. ZIP解压缩文件的工具类【支持多级目录|全】

    ZIP解压缩文件的工具类[支持多级目录|全] 作者:Vashon 网上有很多的加压缩示例代码,但是都只是支持一级目录的操作,如果存在多级目录的话就不行了.本解压缩工具类经过多次检查及重构,最终分享给大 ...

  4. Summary of 2016 International Trusted Computing and Cloud Security Summit

    1)      Welcome Remarks 2)      The advancement of Cloud Computing and Tursted Computing national st ...

  5. 腾讯AI开放平台的接口调用指南

    最近无意发现腾讯AI开放平台上提供了大量好玩的人工智能云服务,而且是完全免费的.只需要用QQ号登录即可.这么好的东西,作为一个程序员,当然要试试了! 从上图可以看出腾讯AI开放平台提供的人工智能服务主 ...

  6. Matlab 图像转极坐标系

    实心圆环 imgVP1=flip(imgVP1,1);  % 水平翻转 polarVP1=polarVolinPlot(imgVP1); % 调用函数空心圆环 [m,n,~]=size(imgVP2) ...

  7. Unexpected Exception caught setting 'username' on 'class com.bj186.crm.web.action.UserAction: Error setting expression 'username' with value ['艾格尼丝', ]

    问题场景: 在使用表单向Action传递数据的时候, 遇到了这个问题, 导致了空指针异常. 问题描述: 10:14:56.622 [http-nio-8080-exec-45] ERROR com.o ...

  8. Vue之computed与watch的使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. Java集合系列之HashMap

    概要 第1部分 HashMap介绍 HashMap简介 HashMap 是一个散列表,它存储的内容是键值对(key-value)映射.HashMap 继承于AbstractMap,实现了Map.Clo ...

  10. image的resizeMode属性

    Image组件必须在样式中声明图片的宽和高.如果没有声明,则图片将不会被呈现在界面上.    我们一般将Image定义的宽和高乘以当前运行环境的像素密度称为Image的实际宽高. 当Image的实际宽 ...