UVA 11354 Bond

本文介绍了一种结合最小生成树、树链剖分和区间查询算法(RMQ)来解决特定图论问题的方法。通过细致的代码实现,文章展示了如何高效地处理基于树结构的数据查询,并提供了完整的C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最小生成树+树链剖分+rmq

#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ms(x,y) memset(x,y,sizeof(x))
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define loop(i,j,k) for (int i=j;i!=-1;i=k[i])
#define inone(x) scanf("%d",&x)
#define intwo(x,y) scanf("%d%d",&x,&y)
#define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define lson x<<1,l,mid
#define rson x<<1|1,mid+1,r
const int N = 2e5+ 10;
const int INF = 0x7FFFFFFF;
int n, m, fa[N], l, r;
int x[N], y[N], z[N], a[N];
int ft[N], nt[N], u[N], v[N], sz;
int dep[N], mx[N], ct[N], top[N];
int f[N], g[N], dp[N][20], lg[N];

int get(int x) { return x == fa[x] ? x : fa[x] = get(fa[x]); }

void AddEdge(int x, int y, int z)
{
	u[sz] = y; v[sz] = z; nt[sz] = ft[x]; ft[x] = sz++;
	u[sz] = x; v[sz] = z; nt[sz] = ft[y]; ft[y] = sz++;
}

void dfs(int x, int f) 
{
	fa[x] = f; mx[x] = 0;
	ct[x] = 1; dep[x] = dep[f] + 1;
	loop(i, ft[x], nt)
	{
		if (u[i] == f) continue;
		dfs(u[i], x);
		ct[x] += ct[u[i]];
		if (ct[u[i]] > ct[mx[x]]) mx[x] = u[i];
	}
}

void Dfs(int x, int t)
{
	top[x] = !t ? x : top[fa[x]];
	f[x] = ++sz;
	if (mx[x]) Dfs(mx[x], 1);
	loop(i, ft[x], nt)
	{
		if (u[i] == fa[x]) continue;
		if (u[i] == mx[x]) { g[f[u[i]]] = v[i]; continue; }
		Dfs(u[i], 0); g[f[u[i]]] = v[i];
	}
}

int rmq(int x, int y)
{
	if (x > y) return 0;
	int r = lg[y - x + 1];
	return max(dp[x][r], dp[y - (1 << r) + 1][r]);
}

int query(int x, int y)
{
	int res = 0;
	for (; top[x] != top[y]; x = fa[top[x]])
	{
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		res = max(res, rmq(f[top[x]], f[x]));
	}
	if (dep[x] > dep[y]) swap(x, y);
	res = max(res, rmq(f[x] + 1, f[y]));
	return res;
}

int main()
{
	int flag = 0;
	while (intwo(n, m) != EOF)
	{
		if (flag) printf("\n"); else flag = 1;
		rep(i, 1, n) fa[i] = i, ft[i] = -1;
		rep(i, 1, m) inthr(x[i], y[i], z[i]), a[i] = i;
		sort(a + 1, a + m + 1, [](int u, int v) {return z[u] < z[v]; });
		rep(i, 1, m)
		{
			int fx = get(x[a[i]]), fy = get(y[a[i]]);
			if (fx == fy) continue;
			fa[fx] = fy; 
			AddEdge(x[a[i]], y[a[i]], z[a[i]]);
		}
		g[1] = dep[0] = ct[0] = sz = 0;
		lg[1] = 0; dfs(1, 0); Dfs(1, 0);
		rep(i, 1, n) dp[i][0] = g[i];
		rep(i, 2, n) lg[i] = lg[i / 2] + 1;
		rep(j, 1, 20)
		{
			rep(i, 1, n)
			{
				if (i + (1 << j - 1) > n) break;
				dp[i][j] = max(dp[i][j - 1], dp[i + (1 << j - 1)][j - 1]);
			}
		}
		inone(m);
		while (m--)
		{
			intwo(l, r);
			printf("%d\n", query(l, r));
		}
		
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值