• P5344 【XR-1】逛森林[倍增优化建图,zkw线段树优化spfa]


    判下连通,离线下来连边,就是个裸的板子了QvQ。
    我们把一堆边连到一个点,那个点连到一堆边,这样就可以满足 [l1,r1] -> to [l2,r2] 了
    可以用 zkw 线段树来跑 spfa,奇怪的姿势增加了。

    // by Isaunoya
    #include<bits/stdc++.h>
    using namespace std;
    struct io {
    	char buf[1 << 25 | 3], *s;
    	int f;
    	io() { f = 0, buf[fread(s = buf, 1, 1 << 25, stdin)] = '
    '; }
    	io& operator >> (int&x) {
    		for(x = f = 0; !isdigit(*s); ++s) f |= *s  == '-';
    		while(isdigit(*s)) x = x * 10 + (*s++ ^ 48);
    		return x = f ? -x : x, *this;
    	}
    };
    
    struct io_out {
    	char buf[1 << 25 | 3], *s = buf;
    	~io_out() { fwrite(buf, 1, s - buf, stdout); }
    	void write(int x) { if(x > 9) write(x / 10); *s++ = x % 10 ^ '0'; }
    	io_out& operator << (int x) {
    		if(x < 0) x = -x, *s++ = '-';
    		write(x); return *this;
    	}
    	io_out& operator << (char x) { *s++ = x; return *this; }
    } out;
    
    int n, m, s;
    const int maxn = 1e6 + 61;
    const int maxd = maxn << 5;
    struct dsu {
    	int fa[maxn];
    	dsu() { for(int i = 0 ; i < maxn ; i ++) fa[i] = i; }
    	int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
    	int operator [](int x) { return find(x); }
    } dsu;
    struct edge { int v, nxt, w; } e[maxd << 1]; int head[maxd], cnt = 0;
    void add(int u, int v, int w) { e[++ cnt] = { v, head[u], w }, head[u] = cnt; }
    
    int dfn[maxn], f[maxn][22], idx = 0, dep[maxn];
    pair <int, int> st[maxn << 1][22];
    
    void dfs(int u) {
    	dfn[u] = ++ idx; st[idx][0] = make_pair(dep[u], u);
    	for(int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].v;
    		if(v == f[u][0]) continue;
    		f[v][0] = u; dep[v] = dep[u] + 1; dfs(v);
    		st[++ idx][0] = make_pair(dep[u], u);
    	}
    }
    
    int lg[maxn << 1];
    int lca(int u, int v) {
    	if((u = dfn[u]) > (v = dfn[v])) u ^= v ^= u ^= v;
    	int len = v - u + 1; len = lg[len];
    	return min(st[u][len], st[v - (1 << len) + 1][len]).second;
    }
    
    int id1[maxn][22], id2[maxn][22]; 
    void link1(int u, int v, int t, int w) {
    	int len = dep[u] - dep[v] + 1;
    	int x = id1[u][lg[len]];
    	int x2 = u, res = len - (1 << lg[len]);
    	for(; res; res ^= res & - res)
    		x2 = f[x2][lg[res & -res]];
    	x2 = id1[x2][lg[len]];
    	add(x, t, w), add(x2, t, w);
    }
    
    void link2(int u, int v, int t, int w) {
    	int len = dep[u] - dep[v] + 1;
    	int x = id2[u][lg[len]];
    	int x2 = u, res = len - (1 << lg[len]);
    	for(; res; res ^= res & - res)
    		x2 = f[x2][lg[res & -res]];
    	x2 = id2[x2][lg[len]];
    	add(t, x, w), add(t, x2, w);
    }
    
    struct que { int u1, v1, u2, v2, w; } q[maxn];
    int t = 0, nd = 0;
    
    int dis[maxd];
    struct zkw_segment_tree {
    	int l, s[maxd << 1];
    	zkw_segment_tree() { l = 1; }
    	
    	void build() {
    		while(l < nd) l <<= 1; --l;
    		for(int i = 1 ; i <= nd ; i ++) s[i + l] = i;
    	}
    	
    	void upd(int x) {
    		x += l; x >>= 1;
    		while(x) {
    			s[x] = dis[s[x << 1]] < dis[s[x << 1 | 1]] ? s[x << 1] : s[x << 1 | 1];
    			x >>= 1;
    		}
    	}
    	void del(int x) { s[x + l] = 0; upd(x); }
    } zkw;
    
    void spfa(int u) {
    	memset(dis, 0x3f, sizeof(dis));
    	dis[u] = 0; zkw.build(), zkw.upd(u);
    //	out << u << '
    ';
    //	out << zkw.s[1] << '
    ';
    //	out << dis[zkw.s[1]] << '
    ';
    	while(dis[zkw.s[1]] != 0x3f3f3f3f) {
    		int u = zkw.s[1];
    		zkw.del(u);
    //		out << u << '
    ';
    		for(int i = head[u]; i; i = e[i].nxt) {
    			int v = e[i].v;
    			if(dis[u] + e[i].w < dis[v]) { dis[v] = dis[u] + e[i].w; zkw.upd(v); }
    		}
    	}
    //	out << '
    ';
    }
    
    signed main() {
    #ifdef LOCAL
    	freopen("testdata.in", "r", stdin);
    #endif
    	io in;
    	in >> n >> m >> s;
    	for(int i = 1 ; i <= m ; i ++) {
    		int op, u1, v1, u2, v2, w;
    		in >> op;
    		if(op == 1) {
    			in >> u1 >> v1 >> u2 >> v2 >> w;
    			if(dsu[u1] ^ dsu[v1] || dsu[u2] ^ dsu[v2])
    				continue;
    			q[++ t] = { u1, v1, u2, v2, w };
    		} else {
    			in >> u1 >> v1 >> w;
    			int fx = dsu[u1], fy = dsu[v1];
    			if(fx == fy) continue; add(u1, v1, w), add(v1, u1, w);
    			dsu.fa[fy] = fx;
    		}
    	}
    	for(int i = 1 ; i <= n ; i ++) if(!dfn[i]) dep[i] = 1, dfs(i);
    	lg[0] = -1; for(int i = 1 ; i <= idx ; i ++) lg[i] = lg[i >> 1] + 1;
    //	for(int i = 1 ; i <= n ; i ++)
    //		out << f[i][0] << '
    ';
    	for(int j = 1 ; j <= 20 ; j ++)
    		for(int i = 1 ; i <= n ; i ++) f[i][j] = f[f[i][j - 1]][j - 1];
    	for(int j = 1 ; j <= 20 ; j ++)
    		for(int i = 1 ; i + (1 << j) - 1 <= idx ; i ++)
    			st[i][j] = min(st[i][j - 1], st[i + (1 << j - 1)][j - 1]);
    	nd = n;
    	for(int i = 1 ; i <= n ; i ++) id1[i][0] = id2[i][0] = i;
    	for(int j = 1 ; j <= 20 ; j ++) {
    		for(int i = 1 ; i <= n ; i ++) {
    			if((1 << j) <= dep[i]) {
    				id1[i][j] = ++nd, id2[i][j] = ++nd;
    				add(id1[i][j - 1], id1[i][j], 0);
    				add(id1[f[i][j - 1]][j - 1], id1[i][j], 0);
    				add(id2[i][j], id2[i][j - 1], 0);
    				add(id2[i][j], id2[f[i][j - 1]][j - 1], 0);
    			}
    		}
    	}
    	for(int i = 1 ; i <= t ; i ++) {
    		int u1, v1, u2, v2, w;
    		u1 = q[i].u1, v1 = q[i].v1, u2 = q[i].u2, v2 = q[i].v2, w = q[i].w;
    		int u = ++nd, l1 = lca(u1, v1), l2 = lca(u2, v2);
    		link1(u1, l1, u, w);
    		if(v1 ^ l1) link1(v1, l1, u, w);
    		link2(u2, l2, u, 0);
    		if(v2 ^ l2) link2(v2, l2, u, 0);
    	}
    	spfa(s);
    	for(int i = 1 ; i <= n ; i ++)
    		if(dis[i] == dis[0]) 
    			out << -1 << ' ';
    		else
    			out << dis[i] << ' ';
    	return 0;
    }
    
    
  • 相关阅读:
    python学习笔记(1)
    一些有趣的使用function
    axios构建请求池处理全局loading状态&&axios避免重复请求
    axios构建缓存池存储基础数据
    文件下载方法
    关于 JS this
    前端 JS 获取 Image 图像 宽高 尺寸
    Html CSS transform matrix3d 3D转场特效
    Github 持续化集成 工作流 Npm包自动化发布
    远程 Linux(Ubuntu 18)添加字体
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12818850.html
Copyright © 2020-2023  润新知