zoukankan      html  css  js  c++  java
  • Wannafly挑战赛2 D.Delete(拓扑排序 + dij预处理 + 线段树维护最小值)

    题目链接  D.Delete

    考虑到原图是个DAG,于是我们可以求出每个点的拓扑序。

    然后预处理出起点到每个点的最短路$ds[u]$,

    和所有边反向之后从终点出发到每个点的最短路$dt[u]$。

    令点$u$的拓扑序为$a(u)$。

    对于特定的一条边$(u, v, w)$,相当于给所有拓扑序为$[a(u) + 1, a[v] - 1]$的点贡献了一条总长度为$ds[u] + dt[v] + w$的路径。

    我们在询问点$u$的时候找到对$u$点贡献的所有路径中长度最小的即可。

    特别地,当$s$无法到达$u$或$u$无法到达t时,输出原图从$s$到$t$的最短路即可。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define lson		i << 1, L, mid
    #define rson		i << 1 | 1, mid + 1, R
    
    typedef long long LL;
    
    const int N  = 1e5 + 10;
    const LL INF = 1e18;
    
    int n, m, s, t, q;
    LL ans;
    LL ds[N], dt[N];
    LL mi[N << 2];
    
    struct node{
    	int u;
    	LL w;
    	friend bool operator < (const node &a, const node &b){
    		return a.w > b.w;
    	}
    };
    
    vector <node> v[N], g[N];
    int a[N], deg[N];
    
    void dij(int s, LL dis[], vector <node> v[]){
    	priority_queue <node> q;
    	static bool vis[N];
    	rep(i, 1, n) dis[i] = 1e18, vis[i] = false;
    	q.push({s, 0});
    	dis[s] = 0;
    	while (!q.empty()){
    		int u = q.top().u; q.pop();
    		if (vis[u]) continue;
    		vis[u] = 1;
    		for (auto edge : v[u]) if (dis[u] + edge.w < dis[edge.u]){
    			dis[edge.u] = dis[u] + edge.w;
    			q.push({edge.u, dis[edge.u]});
    		}
    	}
    }
    
    void getdag(){
    	queue <int> q;
    	int cnt = 0;
    	rep(i, 1, n){
    		if (deg[i] == 0) a[i] = ++cnt, q.push(i);
    	}
    
    	while (!q.empty()){
    		int x = q.front(); q.pop();
    		for (auto edge : v[x]){
    			--deg[edge.u];
    			if (deg[edge.u] == 0) a[edge.u] = ++cnt, q.push(edge.u);
    		}
    	}
    }
    
    void build(int i, int L, int R){
    	mi[i] = INF;
    	if (L == R) return;
    	int mid = (L + R) >> 1;
    	build(lson);
    	build(rson);
    }
    
    void update(int i, int L, int R, int l, int r, LL val){
    	if (l <= L && R <= r){
    		mi[i] = min(mi[i], val);
    		return;
    	}
    
    	int mid = (L + R) >> 1;
    	if (l <= mid) update(lson, l, r, val);
    	if (r >  mid) update(rson, l, r, val);
    }
    
    void query(int i, int L, int R, int x, LL &ans){
    	ans = min(ans, mi[i]);
    	if (L == R) return;
    	int mid = (L + R) >> 1;
    	if (x <= mid) query(lson, x, ans);
    	else query(rson, x, ans);
    }
    
    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);
    		v[x].push_back({y, z});
    		g[y].push_back({x, z});
    		++deg[y];
    	}
    
    	getdag();
    	dij(s, ds, v);
    	dij(t, dt, g);
    
    	build(1, 1, n);
    	rep(i, 1, n){
    		for (auto edge : v[i]){
    			if (a[i] + 1 < a[edge.u] && ds[i] != INF && dt[edge.u] != INF){
    				update(1, 1, n, a[i] + 1, a[edge.u] - 1, ds[i] + dt[edge.u] + edge.w);
    			}
    		}
    	}
    
    	scanf("%d", &q);
    	while (q--){
    		int x;
    		scanf("%d", &x);
    		ans = INF;
    		if (ds[x] == INF || dt[x] == INF){
    			printf("%lld
    ", dt[s]);
    			continue;
    		}
    
    		query(1, 1, n, a[x], ans);
    		if (ans == INF) puts("-1");
    		else printf("%lld
    ", ans);
    	}
    
    	return 0;
    }
    

      

  • 相关阅读:
    [读书笔记] 树莓派 raspberry pi cluster的搭建实践
    [学姿势了] bmp当中插入javascript code
    [读书笔记] 两则之一: Smarter video searching and indexing 更为智能的视频搜索和索引技术
    [读书笔记] 两则之一: 100Gbps传输
    [无知故学习]范式HUFFMAN coding
    [学习笔记]关于CUDA与OPENCL
    [以资鼓励]用于提醒,未来如果在我这台optimus + gtm540的acer NV47H75C上安pnv驱动
    转: Beautiful Numbers (费马小定理)
    Bear and String Distance (贪心 )
    zoj3946--Highway Project
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7936244.html
Copyright © 2011-2022 走看看