luoguP4234 最小差值生成树
Posted ljc00118
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguP4234 最小差值生成树相关的知识,希望对你有一定的参考价值。
https://www.luogu.org/problemnew/show/P4234
按照边的权值从小到大排序,依次加入,并删除能够删除的权值最小的一条边,用 set 维护当前所有边的边权,并查集维护联通性,LCT 维护两点间最小值和 link cut 操作即可
#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
template <typename _T>
inline void read(_T &f) {
f = 0; _T fu = 1; char c = getchar();
while(c < '0' || c > '9') {if(c == '-') fu = -1; c = getchar();}
while(c >= '0' && c <= '9') {f = (f << 3) + (f << 1) + (c & 15); c = getchar();}
f *= fu;
}
const int N = 250000 + 10;
struct ele {
int u, v, a;
bool operator < (const ele A) const {return a < A.a;}
}p[N];
set < pair <int, int> > Min;
int fa[N], ch[N][2], rev[N], minn[N], val[N], wz[N], st[N], f[N], n, m, len, cnt, ans = INT_MAX;
int isroot(int u) {return ch[fa[u]][0] != u && ch[fa[u]][1] != u;}
int get(int u) {return ch[fa[u]][1] == u;}
void update(int u) {
minn[u] = val[u]; wz[u] = u;
if(minn[ch[u][0]] < minn[u] && ch[u][0]) minn[u] = minn[ch[u][0]], wz[u] = wz[ch[u][0]];
if(minn[ch[u][1]] < minn[u] && ch[u][1]) minn[u] = minn[ch[u][1]], wz[u] = wz[ch[u][1]];
}
void pushdown(int u) {
if(rev[u]) {
swap(ch[u][0], ch[u][1]);
rev[ch[u][0]] ^= 1;
rev[ch[u][1]] ^= 1;
rev[u] ^= 1;
}
}
void rotate(int u) {
int old = fa[u], oldd = fa[old], k = get(u);
if(!isroot(old)) ch[oldd][get(old)] = u; fa[u] = oldd;
ch[old][k] = ch[u][k ^ 1]; fa[ch[u][k ^ 1]] = old;
fa[old] = u; ch[u][k ^ 1] = old;
update(old); update(u);
}
void splay(int u) {
st[len = 1] = u;
for(int i = u; !isroot(i); i = fa[i]) st[++len] = fa[i];
for(int i = len; i >= 1; i--) pushdown(st[i]);
for(; !isroot(u); rotate(u)) if(!isroot(fa[u])) rotate(get(u) == get(fa[u]) ? fa[u] : u);
}
void access(int u) {
for(int i = 0; u; i = u, u = fa[u]) {
splay(u);
ch[u][1] = i;
update(u);
}
}
void makeroot(int u) {
access(u);
splay(u);
rev[u] ^= 1;
}
void link(int u, int v) {
makeroot(u);
fa[u] = v;
}
void cut(int u, int v) {
makeroot(u);
access(v);
splay(v);
fa[u] = ch[v][0] = 0;
update(v);
}
int query(int u, int v) {
makeroot(u);
access(v);
splay(v);
return wz[v];
}
int find(int x) {return f[x] == x ? x : f[x] = find(f[x]);}
int main() {
read(n); read(m);
for(int i = 1; i <= n; i++) f[i] = i, val[i] = INT_MAX;
for(int i = 1; i <= m; i++) {
read(p[i].u);
read(p[i].v);
read(p[i].a);
}
sort(p + 1, p + m + 1);
for(int i = 1; i <= m; i++) {
int x = p[i].u, y = p[i].v;
if(find(x) != find(y)) {
cnt++; f[find(x)] = find(y);
val[i + n] = p[i].a;
link(i + n, x);
link(i + n, y);
Min.insert(mp(p[i].a, i));
} else {
if(x == y) continue;
int wz = query(x, y);
val[i + n] = p[i].a;
cut(wz, p[wz - n].u);
cut(wz, p[wz - n].v);
link(i + n, x);
link(i + n, y);
Min.erase(mp(p[wz - n].a, wz - n));
Min.insert(mp(p[i].a, i));
}
if(cnt == n - 1) {
set < pair <int, int> > :: iterator it = Min.begin();
ans = min(ans, p[i].a - it -> first);
}
}
cout << ans << endl;
return 0;
}
以上是关于luoguP4234 最小差值生成树的主要内容,如果未能解决你的问题,请参考以下文章