P5344 【XR-1】逛森林[线段树优化建图]
作者:互联网
判下连通,离线下来连边,就是个裸的板子了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)] = '\n'; }
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 << '\n';
// out << zkw.s[1] << '\n';
// out << dis[zkw.s[1]] << '\n';
while(dis[zkw.s[1]] != 0x3f3f3f3f) {
int u = zkw.s[1];
zkw.del(u);
// out << u << '\n';
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 << '\n';
}
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] << '\n';
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;
}
标签:v1,int,dsu,u1,len,P5344,建图,XR,zkw 来源: https://www.cnblogs.com/Isaunoya/p/12818850.html