zoukankan      html  css  js  c++  java
  • 洛谷 P4234 最小差值生成树(LCT)

    题面

    luogu

    题解

    LCT

    动态树Link-cut tree(LCT)总结

    考虑先按边权排序,从小到大加边

    如果构成一颗树了,就更新答案

    当加入一条边,会形成环.

    贪心地想,我们要最大边权-最小边权最小

    最大边权固定就是新加入的这条边,我们要让最小边权尽量地大

    那么我们可以去掉原先路径上最小的那一条边,这样一定不会差

    以上,可以用LCT维护

    ps:LCT只有点权,所以对于每条边,新建一个节点

    Code

    #include<bits/stdc++.h>
    #define mp make_pair
    #define LL long long
    #define RG register
    const int inf = 2147483647;
    using namespace std;
    template<class T> inline void read(T &x) {
    	x = 0; RG char c = getchar(); bool f = 0;
    	while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;
    	while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();
    	x = f ? -x : x;
    	return ;
    }
    template<class T> inline void write(T x) {
    	if (!x) {putchar(48);return ;}
    	if (x < 0) x = -x, putchar('-');
    	int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;
    	for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
    }
    
    const int N = 250000 + 10;
    
    struct node {
    	int v, m, fa, ch[2], w;//m为最小值,w为位置
    	bool rev;
    }t[N];
    int S[N], top, val[N];
    set<pair<int, int> > Min;
    void putrev(int x) {
    	swap(t[x].ch[0], t[x].ch[1]);
    	t[x].rev ^= 1;
    }
    void pushup(int x) {
    	t[x].m = val[x], t[x].w = x;
    	if (t[x].m > t[t[x].ch[0]].m && t[x].ch[0]) t[x].m = t[t[x].ch[0]].m, t[x].w = t[t[x].ch[0]].w;
    	if (t[x].m > t[t[x].ch[1]].m && t[x].ch[1]) t[x].m = t[t[x].ch[1]].m, t[x].w = t[t[x].ch[1]].w;
    }
    #define get(x) (t[t[x].fa].ch[1] == x)
    bool isroot(int x) {
    	return (t[t[x].fa].ch[0] != x) && (t[t[x].fa].ch[1] != x);
    }
    void pushdown(int x) {
    	if (t[x].rev) {
    		t[x].rev = 0;
    		if (t[x].ch[0]) putrev(t[x].ch[0]);
    		if (t[x].ch[1]) putrev(t[x].ch[1]);
    	}
    }
    void rotate(int x) {
    	int k = get(x), y = t[x].fa, z = t[y].fa;
    	if (!isroot(y)) t[z].ch[get(y)] = x;
    	t[x].fa = z;
    	t[t[x].ch[k^1]].fa = y; t[y].ch[k] = t[x].ch[k^1];
    	t[y].fa = x; t[x].ch[k^1] = y;
    	pushup(y);
    }
    void splay(int x) {
    	S[top = 1] = x;
    	for (RG int i = x; !isroot(i); i = t[i].fa) S[++top] = t[i].fa;
    	for (RG int i = top; i; i--) pushdown(S[i]);
    	while (!isroot(x)) {
    		int y = t[x].fa;
    		if (!isroot(y))
    			(get(x) ^ get(y)) ? rotate(x) : rotate(y);
    		rotate(x);
    	}
    	pushup(x);
    }
    
    void access(int x) {for (int y = 0; x; y = x, x = t[x].fa)splay(x), t[x].ch[1] = y, pushup(x);}
    
    void makeroot(int x) {access(x); splay(x); putrev(x);}
    void link(int x, int y) {
    	makeroot(x);
    	t[x].fa = y;
    }
    void cut(int x, int y) {
    	makeroot(x);
    	access(y);
    	splay(y);
    	t[x].fa = t[y].ch[0] = 0; pushup(y);
    }
    void split(int x, int y) {makeroot(x); access(y); splay(y);}
    
    struct Node {
    	int u, v, w;
    	bool operator <(Node z) const {
    		return w < z.w;
    	}
    }p[N];
    int fa[N];
    int find(int x) {
    	return fa[x] == x ? x : fa[x] = find(fa[x]);
    }
    int main() {
    	int n, m, cnt = 0, ans = inf;
    
    	read(n), read(m);
    	for (int i = 1; i <= m; i++)
    		read(p[i].u), read(p[i].v), read(p[i].w);
    	sort(p+1, p+1+m);
    	for (int i = 1; i <= n; i++) fa[i] = i, val[i] = inf;
    	for (int i = 1; i <= m; i++) {
    		int x = p[i].u, y = p[i].v;
    		if (x == y) continue;
    		val[i + n] = p[i].w;
    		if (find(x) != find(y)) {
    			cnt++; fa[find(y)] = find(x);
    			link(i + n, x);	link(i + n, y);
    			Min.insert(mp(p[i].w, i));
    		} else {
    			split(x, y);
    			int wz = t[y].w;
    			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].w, wz - n));
    			Min.insert(mp(p[i].w, i));
    		}
    		if (cnt == n-1)
    			ans = min(ans, p[i].w - (Min.begin()->first));
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    
    
  • 相关阅读:
    字符串对比
    时间转换
    fJ字符串
    Codeforces 1526D
    HDU
    树链剖分入门
    AcWing 252. 树(点分治模版题)
    HDU-4487 Maximum Random Walk(概率dp)
    acwing 316 减操作(dp)
    CodeForces
  • 原文地址:https://www.cnblogs.com/zzy2005/p/10313064.html
Copyright © 2011-2022 走看看