zoukankan      html  css  js  c++  java
  • 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 '
    '
    #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
    ",ans[t]);
    	}
    }
    
  • 相关阅读:
    百度之星资格赛1001——找规律——大搬家
    HDU1025——LIS——Constructing Roads In JGShining's Kingdom
    DP(递归打印路径) UVA 662 Fast Food
    递推DP UVA 607 Scheduling Lectures
    递推DP UVA 590 Always on the run
    递推DP UVA 473 Raucous Rockers
    博弈 HDOJ 4371 Alice and Bob
    DFS(深度) hihoCoder挑战赛14 B 赛车
    Codeforces Round #318 [RussianCodeCup Thanks-Round] (Div. 2)
    DP(DAG) UVA 437 The Tower of Babylon
  • 原文地址:https://www.cnblogs.com/uid001/p/10986812.html
Copyright © 2011-2022 走看看