Wannafly挑战赛2D Delete (最短路好题)
Posted uid001
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Wannafly挑战赛2D Delete (最短路好题)相关的知识,希望对你有一定的参考价值。
大意: 给定DAG, 给定点$S,T$, 每次询问给出点$x$, 求删除$x$后的$S->T$的最短路, 询问之间独立.
删除点$x$的最短路一定要经过一条边$(u,v)$, 满足$u$拓扑序在$x$前, $v$拓扑序在$x$后. (对于拓扑序相同的点不会有影响)
这样可以枚举每一条边, 用线段树维护删除每个点的答案.
#include <iostream> #include <sstream> #include <algorithm> #include <cstdio> #include <math.h> #include <set> #include <map> #include <queue> #include <string> #include <string.h> #include <bitset> #include <unordered_map> #define REP(i,a,n) for(int i=a;i<=n;++i) #define PER(i,a,n) for(int i=n;i>=a;--i) #define hr putchar(10) #define pb push_back #define lc (o<<1) #define rc (lc|1) #define mid ((l+r)>>1) #define ls lc,l,mid #define rs rc,mid+1,r #define x first #define y second #define io std::ios::sync_with_stdio(false) #define endl ‘\n‘ #define DB(a) (REP(__i,1,n) cout<<a[__i]<<‘ ‘;hr;) using namespace std; typedef long long ll; #ifdef ONLINE_JUDGE const int N = 1e6+10; #else const int N = 999; #endif const ll INF = 0x3f3f3f3f3f3f3f3f; int n,m,S,T,deg[N],a[N],vis[N],no[N]; struct _ int to,w;; vector<_> g[N], gg[N]; ll d1[N], d2[N], tr[N<<2], ans[N]; queue<int> q; void topo() REP(i,1,n) if (!deg[i]) q.push(i); int clk = 0; while (q.size()) int u = q.front(); q.pop(); a[u] = ++clk, no[clk] = u; for (auto &e:g[u]) if (!--deg[e.to]) q.push(e.to); struct __ int u; ll w; bool operator < (const __ &rhs) const return w>rhs.w; ; void DP(ll d[], vector<_> g[], int s) memset(d,0x3f,sizeof d1); memset(vis,0,sizeof vis); priority_queue<__> q; q.push(s,d[s]=0); while (q.size()) int u = q.top().u; q.pop(); if (vis[u]) continue; vis[u] = 1; for (auto &e:g[u]) ll dd = d[u]+e.w; if (dd<d[e.to]) q.push(e.to,d[e.to]=dd); void update(int o, int l, int r, int ql, int qr, ll v) if (ql<=l&&r<=qr) return tr[o]=min(tr[o],v),void(); if (mid>=ql) update(ls,ql,qr,v); if (mid<qr) update(rs,ql,qr,v); void dfs(int o, int l, int r) if (l==r) if (d1[no[l]]==INF||d2[no[l]]==INF) ans[no[l]]=d1[T]; else ans[no[l]]=tr[o]; else tr[lc]=min(tr[lc],tr[o]); tr[rc]=min(tr[rc],tr[o]); dfs(ls),dfs(rs); 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); g[x].pb(y,z),++deg[y]; gg[y].pb(x,z); topo(); DP(d2,gg,T); DP(d1,g,S); memset(tr,0x3f,sizeof tr); REP(i,1,n) for (auto e:g[i]) if (a[e.to]!=a[i]+1&&d1[i]!=INF&&d2[e.to]!=INF) update(1,1,n,a[i]+1,a[e.to]-1,e.w+d1[i]+d2[e.to]); dfs(1,1,n); int q; scanf("%d", &q); while (q--) int t; scanf("%d", &t); printf("%lld\n",ans[t]);
以上是关于Wannafly挑战赛2D Delete (最短路好题)的主要内容,如果未能解决你的问题,请参考以下文章