社区讨论

LCT 7pts MLE 悬关求调

P4234最小差值生成树参与者 2已保存回复 5

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
5 条
当前快照
1 份
快照标识符
@mk0wqadx
此快照首次捕获于
2026/01/05 16:37
2 个月前
此快照最后确认于
2026/01/08 21:20
2 个月前
查看原帖
CPP
#include <bits/stdc++.h>
//#define int long long
#define PII pair<int, int>

using namespace std;

int n, m, q;
struct EDGE
{
	int u, v, w;
	bool operator < (const EDGE xx) const
	{
		return w < xx.w;
	}
}edge[200010];
bool vis[200010];
int idx;
struct node
{
	int fa;
	int ls, rs;
	int mx;
	bool lz;
}tree[400010];
int ans = 1145141919810;

bool isroot(int u)
{
	return tree[tree[u].fa].ls != u && tree[tree[u].fa].rs != u;
}

void pushup(int x)
{
	tree[x].mx = x;
	if(tree[tree[x].ls].mx > n && (tree[x].mx <= n || tree[x].mx > tree[tree[x].ls].mx)) tree[x].mx = tree[tree[x].ls].mx;
	if(tree[tree[x].rs].mx > n && (tree[x].mx <= n || tree[x].mx > tree[tree[x].rs].mx)) tree[x].mx = tree[tree[x].rs].mx;
}

void pushdown(int u)
{
    if(tree[u].lz)
	{
        swap(tree[u].ls, tree[u].rs);
        if(tree[u].ls) tree[tree[u].ls].lz ^= 1;
        if(tree[u].rs) tree[tree[u].rs].lz ^= 1;
        tree[u].lz = false;
    }
}

void push(int u)
{
    if(!isroot(u)) push(tree[u].fa);
    pushdown(u);
}

void rotate(int u)
{
    int fa = tree[u].fa, gfa = tree[fa].fa;
    if(!isroot(fa))
	{
        if(tree[gfa].ls == fa) tree[gfa].ls = u;
        else tree[gfa].rs = u;
    }
    tree[u].fa = gfa;
    if(tree[fa].ls == u)
	{
        tree[fa].ls = tree[u].rs;
        if(tree[u].rs) tree[tree[u].rs].fa = fa;
        tree[u].rs = fa;
    }
	else
	{
        tree[fa].rs = tree[u].ls;
        if(tree[u].ls) tree[tree[u].ls].fa = fa;
        tree[u].ls = fa;
    }
    tree[fa].fa = u;
    pushup(fa);
    pushup(u);
}

void splay(int u)
{
    push(u);
    while(!isroot(u))
	{
        int fa = tree[u].fa;
        int gfa = tree[fa].fa;
        if(!isroot(fa))
		{
            if((tree[gfa].ls == fa) == (tree[fa].ls == u)) rotate(fa);
            else rotate(u);
        }
        rotate(u);
    }
}

void access(int u)
{
	for(int i = 0; u; i = u, u = tree[u].fa)
	{
		splay(u);
		tree[u].rs = i;
		pushup(u);
	}
}

void makeroot(int u)
{
	access(u);
	splay(u);
	tree[u].lz ^= 1;
}

void split(int u, int v)
{
	makeroot(u);
	access(v);
	splay(v);
}

int findroot(int u)
{
	access(u);
	splay(u);
	while(tree[u].ls)
	{
		pushdown(u);
		u = tree[u].ls;
	}
	splay(u);
	return u;
}

void link(int u, int v)
{
	makeroot(u);
	if(findroot(v) != u) tree[u].fa = v;
}

void cut(int u, int v)
{
    split(u, v);
    tree[v].ls = tree[u].fa = 0;
    pushup(v);
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	int idx = 0;
	for(int i = 1;i <= m;i ++)
	{
		int u, v, w;
		cin >> u >> v >> w;
		if(u != v) edge[++ idx] = {u, v, w};
	}
	m = idx;
	sort(edge + 1, edge + m + 1);
//	for(int i = 1;i <= m;i ++) cout << edge[i].u << " " << edge[i].v << " " << edge[i].w << "\n";
	int mr = 1, ltk = n, sum = 0, kkk = 1;
	for(int i = 1;i <= m;i ++)
	{
		ltk ++;
		if(edge[i].u == edge[i].v)
		{
			vis[i] = 1;
			continue;
		}
		if(findroot(edge[i].u) != findroot(edge[i].v)) link(edge[i].u, ltk), link(ltk, edge[i].v), sum ++;
		else
		{
			split(edge[i].u, edge[i].v);
			mr = tree[edge[i].v].mx;
			vis[mr - n] = 1;
			splay(mr);
			tree[tree[mr].ls].fa = tree[tree[mr].rs].fa = 0;
			link(edge[i].u, ltk), link(ltk, edge[i].v);
		}
		while(vis[kkk] && kkk <= i) kkk ++; 
		if(sum >= n - 1 ) ans = min(ans, edge[i].w - edge[kkk].w);
	}
	cout << ans;
	return 0;
}

回复

5 条回复,欢迎继续交流。

正在加载回复...