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]);
    	}
    }
    
  • 相关阅读:
    18文件权限管理
    17用户身份管理
    16Shell脚本—计划任务服务程序
    15Shell脚本—流程控制
    14Shell脚本—判断语句
    13Shell脚本—编写简单脚本
    12Vim在系统配置中的应用示例
    11Vim文本编辑器
    10重要的环境变量
    09命令行通配符和转义字符
  • 原文地址:https://www.cnblogs.com/uid001/p/10986812.html
Copyright © 2011-2022 走看看