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 (最短路好题)的主要内容,如果未能解决你的问题,请参考以下文章

Wannafly挑战赛13

Wannafly挑战赛23 A字符串

Wannafly挑战赛24

Wannafly挑战赛27

Wannafly挑战赛3

Wannafly挑战赛21A