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]); } }