zoukankan      html  css  js  c++  java
  • Luogu4234:最小差值生成树

    题面

    luogu

    Sol

    好久没写(LCT)
    然而写跪了(TAT)

    把边从小到大加入森林
    如果形成环,就替换最小的边
    如果已经是树,更新答案
    (LCT)维护

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int _(4e5 + 5);
    
    IL int Input(){
    	RG int x = 0, z = 1; RG char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    	for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    	return x * z;
    }
    
    int n, m, fa[_], ch[2][_], mn[_], val[_], rev[_], ans, S[_], bt[_], vis[_];
    struct Edge{
    	int u, v, w;
    
    	IL bool operator <(RG Edge B) const{
    		return w < B.w;
    	}
    } edge[_];
    
    IL int Son(RG int x){
    	return ch[1][fa[x]] == x;
    }
    
    IL int Isroot(RG int x){
    	return ch[0][fa[x]] != x && ch[1][fa[x]] != x;
    }
    
    IL int Chk(RG int x, RG int y){
    	return val[x] < val[y] ? x : y;
    }
    
    IL void Update(RG int x){
    	mn[x] = Chk(x, Chk(mn[ch[0][x]], mn[ch[1][x]]));
    }
    
    IL void Reverse(RG int x){
    	if(!x) return;
    	rev[x] ^= 1, swap(ch[0][x], ch[1][x]);
    }
    
    IL void Pushdown(RG int x){
    	if(!rev[x]) return;
    	rev[x] = 0, Reverse(ch[0][x]), Reverse(ch[1][x]);
    }
    
    IL void Rotate(RG int x){
    	RG int y = fa[x], z = fa[y], c = Son(x);
    	if(!Isroot(y)) ch[Son(y)][z] = x; fa[x] = z;
    	ch[c][y] = ch[!c][x], fa[ch[c][y]] = y;
    	ch[!c][x] = y, fa[y] = x, Update(y);
    }
    
    IL void Splay(RG int x){
    	S[S[0] = 1] = x;
    	for(RG int y = x; !Isroot(y); y = fa[y]) S[++S[0]] = fa[y];
    	while(S[0]) Pushdown(S[S[0]--]);
    	for(RG int y = fa[x]; !Isroot(x); Rotate(x), y = fa[x])
    		if(!Isroot(y)) Son(x) ^ Son(y) ? Rotate(x) : Rotate(y);
    	Update(x);
    }
    
    IL void Access(RG int x){
    	for(RG int y = 0; x; y = x, x = fa[x]) Splay(x), ch[1][x] = y, Update(x);
    }
    
    IL void Makeroot(RG int x){
    	Access(x), Splay(x), Reverse(x);
    }
    
    IL void Link(RG int x, RG int y){
    	Makeroot(x), fa[x] = y;
    }
    
    IL void Split(RG int x, RG int y){
    	Makeroot(x), Access(y), Splay(y);
    }
    
    IL void Cut(RG int x, RG int y){
    	Split(x, y), ch[0][y] = fa[x] = 0, Update(y);
    }
    
    IL int Find(RG int x){
    	return bt[x] == x ? x : bt[x] = Find(bt[x]);
    }
    
    int main(RG int argc, RG char *argv[]){
    	n = Input(), m = Input(), ans = val[0] = 233233;
    	for(RG int i = 1; i <= n + m; ++i) bt[i] = i, val[i] = 23333;
    	for(RG int i = 1; i <= m; ++i){
    		RG int u = Input(), v = Input(), w = Input();
    		edge[i] = (Edge){u, v, w};
    	}
    	sort(edge + 1, edge + m + 1);
    	for(RG int i = 1, tot = 0, t = 1; i <= m; ++i){
    		RG int x = Find(edge[i].u), y = Find(edge[i].v);
    		val[i + n] = edge[i].w;
    		if(x == y){
    			if(edge[i].u == edge[i].v) continue;
    			Split(edge[i].u, edge[i].v);
    			RG int pos = mn[edge[i].v];
    			Cut(edge[pos - n].u, pos), Cut(edge[pos - n].v, pos);
    			Link(edge[i].u, i + n), Link(edge[i].v, i + n);
    			vis[i] = 1, vis[pos - n] = 0;
    		}
    		else{
    			vis[i] = 1, bt[x] = y, ++tot;
    			Link(edge[i].u, i + n), Link(edge[i].v, i + n);
    		}
    		while(!vis[t]) ++t;
    		if(tot == n - 1) ans = min(ans, edge[i].w - edge[t].w);
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    
    
  • 相关阅读:
    svn command line tag
    MDbg.exe(.NET Framework 命令行调试程序)
    Microsoft Web Deployment Tool
    sql server CI
    VS 2010 One Click Deployment Issue “Application Validation did not succeed. Unable to continue”
    mshtml
    大厂程序员站错队被架空,只拿着五折工资!苟活和离职,如何选择?
    揭秘!Windows 为什么会蓝屏?微软程序员竟说是这个原因...
    喂!千万别忘了这个C语言知识!(~0 == -1 问题)
    Linux 比 Windows 更好,谁反对?我有13个赞成理由
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8625117.html
Copyright © 2011-2022 走看看