[Wannafly挑战赛2D-Delete]最短路
[Wannafly挑战赛2D-Delete]最短路
题目描述
给定一张 n 个点,m 条边的带权有向无环图,同时给定起点 S 和终点 T ,一共有 q 个询问,每次询问删掉某个点和所有与它相连的边之后 S 到 T 的最短路,询问之间互相独立(即删除操作在询问结束之后会立即撤销),如果删了那个点后不存在 S 到 T 的最短路,则输出 −1 。点的编号为 1 到 n 。
输入格式
第一行四个正整数表示 n,m,S,T ,意义如题所述。
接下来 m 行每行三个正整数 x,y,z ,表示有一条 x 到 y 的有向边,权值为 z 。
接下来一行一个正整数 Q 表示询问次数。
最后 Q 行每行一个正整数 k 表示这次询问要删除点 k 。
输出格式
输出 Q 行,每行一个整数表示答案。
样例一
input
6 7 1 5
1 2 2
2 3 4
3 4 3
4 5 5
3 5 9
1 6 10
6 5 13
4
3
4
2
6
output
23
15
23
14
限制与约定
对于 100% 的数据,1≤S,T,x,y,k≤n≤10^5 ;1≤Q≤10^5 ;1≤m≤2×10^5 ;0≤z≤10^9
Solution
题意为:给定一个,多次询问任意删掉一个点之后,S到T的最短路。
首先,这是一个,因此S到T的最短路是可以沿拓扑序DP直接求出的,因此我们不花半点力气,就得到了一个的算法。
现在我们考虑删点对于一个的影响,即之前通过拓扑序求出的拓扑图其中一个点不能通过。
先特判S到T不连通的情况,直接输出-1即可。
现在我们保证了S到T有一条可行路径。考虑拓扑图之外的边对其影响,它们会提供一种可行的方式跨过被删点连向之后的节点,形成最短路的总代价为 ,而这一条路会对在拓扑图中u,v两点之间所有点产生相同的影响。即u,v之间所有点形成的最短路,都能用这一条边形成的路径代替(不保证最短,只保证可行)。
于是问题变成了:一堆边会改变拓扑序中连续的一段区间[l,r]的点的代价,求任意某点的最优代价。区间修改+单点查询,线段树维护最小值即可。
时间复杂度为 。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=1e9+7;
const ll INF=1ll<<60;
const int MAXN=1e5+500;
/*--------------------------------------------------------------------*/
struct enode{int v; ll c; };
vector<enode> e1[MAXN],e2[MAXN];
int d1[MAXN],d2[MAXN],dfn[MAXN];
ll f1[MAXN],f2[MAXN];
queue<int> que;
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }return x*f;
}
inline char readc()
{char c=getchar();while (!isalnum(c)) c=getchar();return c;
}
struct Segment_Tree
{struct treenode{int l,r; ll s; } tree[MAXN<<2];void build(int x,int l, int r){tree[x].s=INF;if ((tree[x].l=l)==(tree[x].r=r)) return;int mid=(tree[x].l+tree[x].r)>>1;build(x<<1,l,mid);build(x<<1|1,mid+1,r);}void change(int x,int L,int R,ll val){if (L<=tree[x].l&&tree[x].r<=R) { tree[x].s=min(tree[x].s,val); return; }int mid=(tree[x].l+tree[x].r)>>1;if (L<=mid) change(x<<1,L,R,val);if (mid<R) change(x<<1|1,L,R,val);}ll query(int x,int y){if (tree[x].l==tree[x].r) return tree[x].s;int mid=(tree[x].l+tree[x].r)>>1;if (y<=mid) return min(tree[x].s,query(x<<1,y));else return min(tree[x].s,query(x<<1|1,y));}
} segment;
int main()
{//freopen("shortest.in","r",stdin);//freopen("shortest.out","w",stdout);int n=read(),m=read(),S=read(),T=read();for (int i=1;i<=m;i++){int u=read(),v=read(),c=read();e1[u].push_back((enode){v,c});e2[v].push_back((enode){u,c});d1[v]++; d2[u]++;}int Dfn=0;for (int i=1;i<=n;i++) f1[i]=INF; f1[S]=0;for (int i=1;i<=n;i++) if (d1[i]==0) que.push(i); while (!que.empty()){int q=que.front();dfn[q]=++Dfn;que.pop();for (int i=0;i<e1[q].size();i++){int to=e1[q][i].v,c=e1[q][i].c;d1[to]--;f1[to]=min(f1[to],f1[q]+c);if (d1[to]==0) que.push(to);}}que.push(T);for (int i=1;i<=n;i++) f2[i]=INF; f2[T]=0;for (int i=1;i<=n;i++) if (d2[i]==0) que.push(i);while (!que.empty()){int q=que.front();que.pop();for (int i=0;i<e2[q].size();i++){int to=e2[q][i].v,c=e2[q][i].c;d2[to]--;f2[to]=min(f2[to],f2[q]+c);if (d2[to]==0) que.push(to);}}segment.build(1,1,n);for (int i=1;i<=n;i++) for (int j=0;j<e1[i].size();j++)if (f1[i]!=INF&&f2[e1[i][j].v]!=INF&&dfn[i]+1<dfn[e1[i][j].v]) segment.change(1,dfn[i]+1,dfn[e1[i][j].v]-1,f1[i]+f2[e1[i][j].v]+e1[i][j].c);int Case=read();while (Case--){int x=read();if (f1[x]==INF||f2[x]==INF) printf("%lld\n",f1[T]);else {ll q=segment.query(1,dfn[x]);printf("%lld\n",q==INF?-1:q);}}return 0;
}
[Wannafly挑战赛2D-Delete]最短路相关推荐
- Wannafly挑战赛22游记
Wannafly挑战赛22游记 幸运的人都是相似的,不幸的人各有各的不幸. --题记 A-计数器 题目大意: 有一个计数器,计数器的初始值为\(0\),每次操作你可以把计数器的值加上\(a_1,a_2 ...
- Wannafly挑战赛19
Wannafly挑战赛19 A. 队列Q 需要支持把一个元素移到队首,把一个元素移到队尾,移到队首就直接放到队首前面那个位置,原位置标为0,队尾同理. #include <bits/stdc++ ...
- Wannafly挑战赛18
Wannafly挑战赛18 A. 序列 先考虑暴力,相邻两个树之间乘上给定的三种数,递推出下一个位置填什么,然后再check一下,最后一位是否为1即可.这样时间显然不行,但是给我们一种思路,就是中间的 ...
- Wannafly 挑战赛27 题解
Wannafly 挑战赛27 题目连接 https://www.nowcoder.com/acm/contest/215#question A.灰魔法师 题目 题解 考虑到可能的完全平方数只有4004 ...
- Wannafly挑战赛24
Wannafly挑战赛24 题目连接 https://www.nowcoder.com/acm/contest/186#question A.石子游戏 题解 注意到当石子个数为偶数的时候,每回合都会减 ...
- Wannafly挑战赛18B 随机数
Wannafly挑战赛18B 随机数 设\(f_i\)表示生成\(i\)个数有奇数个1的概率. 那么显而易见的递推式:\(f_i=p(1-f_{i-1})+(1-p)f_{i-1}=(1-2p)f_{ ...
- Wannafly挑战赛14 A-直角三棱锥
Wannafly挑战赛14 A-直角三棱锥 链接:https://www.nowcoder.com/acm/contest/81/A 来源:牛客网 题目描述 在三维空间中,平面 x = 0, y = ...
- Wannafly挑战赛27 C蓝魔法师
链接Wannafly挑战赛27 C蓝魔法师 给出一棵树,求有多少种删边方案,使得删后的图每个连通块大小小于等于\(k\),\(n,k\leq 2*10^3\) 假设我们正在考虑\(i\)这个子树,那么 ...
- Wannafly挑战赛26-B 冥土追魂
地址:https://www.nowcoder.com/acm/contest/212/B 思路:对于行列选取,是选择所有行中的最大值的最小值,当是并不能用贪心来做,例如 2 2 2 7 8 1 9 ...
最新文章
- 【PHP】安装 ssh2 模块
- ubuntu最基本的软件
- python 最小硬币数_Python之动态规划(最少硬币数找零)
- 有必要服务器虚拟化吗,服务器虚拟化有必要吗
- 以撩妹为例,5分钟让你秒懂深度学习!
- python tkinter库函数详解_Python使用tkinter库进行GUI编程中常用事件处理方式汇总
- javascript 停止事件冒泡以及阻止默认事件冒泡
- 工程师,你的钱究竟从哪来?
- spire.pdf系列文章
- Java的GUI学习八(键盘码查询器)
- paip.java gui swt/jface 最佳实践
- (转)嘉信理财再度全面降佣,它会否成为投资界的Amazon?
- FTP 文件上传跟下载
- web 安全-电脑端口(全部)
- Lingo教育版免费申请流程
- 如何用LOTO示波器TDR方法测试电线长度?
- WIFI智能插座Homekit
- shopnc nodejs安装
- 【51单片机】十分钟学会定时器中断¹
- Front Immunol 复现 | 1. GEO数据下载及sva批次校正(PCA可视化)
热门文章
- 拿了年终奖后,发现自己又拖后腿了?对不起,可能事实并没有那么糟糕...
- 继Science发文后,Nature也发文评论曹雪涛“误用图片”调查结果
- 酸了!第一名+第三名的学霸情侣,分别直博清华、人大…
- 你在孩子身上偷的懒,终将会变成最大的遗憾
- 实用Python库,这几个你认识不?
- linux+4.4+android,Ubuntu 14.04 x64配置Android 4.4 kitkat编译环境的方法
- php中怎样表示组合框,php – 如何实现动态组合框选择系统
- c语言字符比较思路,C语言讲解思路资料
- 机器人等级考试一级教具_全国青少年机器人技术等级考试(一级):基本结构...
- 计算机原理试题b,计算机组成原理试题B答案