首页 > 其他分享 >树(tree) - 题解(带权并查集)

树(tree) - 题解(带权并查集)

时间:2024-08-02 18:41:08浏览次数:5  
标签:11 10 结点 ch 题解 tree 带权 条边 测试用例

树(tree)

时间限制:C/C++ 2000MS,其他语言 4000MS
内存限制:C/C++ 256MB,其他语言 512MB

描述

给定一个 \(n\) 个结点,\(n−1\) 条边的有根树。
第 \(i\) 条边可以用 (\(a_i,b_i\)) 来描述,它表示连接结点 \(a_i\) 和结点 \(b_i\) 的一条边,其中结点 \(a_i\) 是结点 \(b_i\) 的父节点。
一共有 \(n−1\) 次查询:第 \(i\) 次查询包含一个整数 \(c_i\),询问由前 \(i\) 条边构成的图(森林)中从结点 \(c_i\) 开始的最长简单路径的长度。
数据保证不存在 \(j\) 使得 \(1≤j≤i\) 且 \(b_j=c_i\),即 \(c_i\) 是前 \(i\) 条边构成的森林中一棵树的根。

输入描述

输入有多组测试用例,第一行包含一个整数 \(t(1≤t≤10^5)\) ,表示接下来有 \(t\) 组测试用例。
每组测试用例第一行包含一个整数 \(n(2≤n≤10^6)\),表示树的结点数。
接下来 \(n−1\) 行每行包含三个整数 \(a_i,b_i,c_i\) \((1≤a_i,b_i,c_i≤n,a_i≠b_i)\),表示结点 \(b_i\) 的父结点是结点 \(a_i\) ,第 \(i\) 次询问是 \(c_i\)。
数据保证:
对每一个测试用例,\(n−1\) 条边形成一个有根树。
对每一个测试用例,对任意 \(1≤i≤n−1\),保证不存在 \(j\) 使得 \(1≤j≤i\) 且 \(b_j=c_i\)。
所有测试用例中,\(n\) 的总和不超过 \(10^6\)

输出描述

对每一个测试用例,一行输出 \(n−1\) 个整数,第 \(i\) 个整数表示第 \(i\) 次询问的答案。

用例输入 1

6
4
3 4 1
2 3 1
1 2 1
4
3 4 3
2 1 2
3 2 3
4
1 2 1
3 4 3
2 3 1
4
2 3 1
2 4 2
1 2 1
2
1 2 1
2
2 1 2

用例输出 1

0 0 3
1 1 2
1 1 3
0 1 2
1
1

用例输入 2

2
5
1 2 3
1 3 4
3 4 1
1 5 1
15
10 14 10
5 8 5
1 3 1
4 7 10
2 5 2
1 2 1
3 4 1
9 10 9
11 13 11
5 6 1
10 12 9
8 9 1
11 15 11
7 11 1

用例输出 2

0 0 2 2
1 1 1 1 2 3 3 2 1 3 2 6 1 6

提示

\(1≤t≤10^5\)
\(2≤n≤10^6\)

解析

由题意得 \(c_i\) 为某树的根;
由于不可能将两个非根结点连接在一起,所以 \(b_i\) 一定是树根。

用带权并查集处理深度和子树的最大深度即可。

代码

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;

inline int read()
{
	int x=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^'0');ch=getchar();}
	return x*w;
}

const int N=2e6+5,M=5e6+5;
int T,n;

int fa[N],dist[N],maxdep[N];
inline void uInit()
{
	for(int i=1;i<=n;i++)
	{
		fa[i]=i;
		maxdep[i]=dist[i]=0;
	}
	return;
}
int uask(const int x)
{
	if(fa[x]==x) return x;
	else
	{
		const int oldfa=fa[x];
		fa[x]=uask(fa[x]);
		dist[x]=dist[x]+dist[oldfa];
		maxdep[fa[x]]=max(maxdep[fa[x]],dist[x]); //ÕâÒ»ÐпÉÒÔÊ¡ÂÔ 
		return fa[x];
	}
}
inline void umerge(const int x,const int y)
{
	const int rtx=uask(x),rty=uask(y);
	if(rtx==rty) return;
	fa[rty]=rtx;
	dist[rty]=dist[x]+1-dist[y]; //dist[y]+dist[rty]=dist[x]+dis(x,y)
	maxdep[rtx]=max(maxdep[rtx],maxdep[rty]+dist[rty]);
	return;
}

int main()
{
	T=read();
	while(T--)
	{
		n=read();
		uInit();
		for(int i=1;i<n;i++)
		{
			int a=read(),b=read(),q=read();
			umerge(a,b);
			printf("%d ",maxdep[q]);
		}
		putchar('\n');
	}
	return 0;
}

标签:11,10,结点,ch,题解,tree,带权,条边,测试用例
From: https://www.cnblogs.com/jerrycyx/p/18339364

相关文章

  • Luogu P5005 中国象棋 - 摆上马 / Luogu P8756 国际象棋 题解 [ 蓝 ] [ 状压 dp ] [
    国际象棋:模板棋盘状压。摆上马:需要点思维的棋盘状压,相比上一道题加了“蹩马脚”的设定。Easy_version:国际象棋概述一下此类棋盘问题的思路:用二进制数表示出棋盘上某一行的状态。用位运算预处理出合法的单行状态,以及需要用到的一些东西。用位运算判断前一行或者前几行能否......
  • Luogu P3959 宝藏 题解 [ 紫 ] [ 状压 dp ] [ 二项式定理 ]
    宝藏:一个对着蓝书代码调都能调两个小时的大毒瘤,但是思路还是很值得借鉴的,有普通状压和三进制状压两种做法,或者暴搜剪枝也可以(这里不介绍暴搜剪枝做法)。普通状压做法观察到\(n\le12\),首先想到状压。但考虑到普通的状压不太行,因为\(K\)这个数算在代价里,会导致这个dp有后效......
  • [AGC023F] 01 on Tree
    题意给定一棵\(n\)个节点的树,每个点都有权值\(0/1\),每次删除一个没有父亲的节点,并将权值放在序列末尾。求该序列最小的逆序对数。Sol删除不好做,只能\(\text{dp}\)。考虑把删除改成合并,每次合并\(x\)和\(fa_x\)表示将\(x\)紧接在\(fa_x\)后面。这样维护\(n\)个......
  • BZOJ2839/LG10596 集合计数 题解(二项式反演+扩展欧拉定理)
    题目大意:一个有\(N\)个元素的集合有\(2^N\)个不同子集(包含空集),现在要在这\(2^N\)个集合中取出若干集合(至少一个),使得它们的交集的元素个数为\(K\),求取法的方案数,答案模\(10^9+7\)。为表述方便,不妨设这\(i\)个元素分别为\(1\simn\)。前置知识:二项式反演。考虑设\(g(......
  • 题解:CF1537E2 Erase and Extend (Hard Version)
    CF1537E2EraseandExtend题解分析通过观察题目,可以证明结果一定是由多次前缀复制得来的。题目要求你进行删和复制的操作,与其交替着操作,不如直接先删到最优的前缀再进行复制。现在就是要找最优的前缀。从头一位一位往后遍历。用\(l\)来存储目前最优前缀的长度,第\(i\)位......
  • 题解:CF1301B Motarack's Birthday
    CF1301DTimetoRun题解思维题。分析把一个格子视作一个点,每个点的度数都是偶数,所以这是一张欧拉图。而需要走遍整个方格图,可以证明只要\(k\)不超过\(4nm-2n-2m\)就一定有解。很明显存在很多种方案,这里我用的方案是:从左上角出发,向右走\(m-1\)步到头,再向左走\(m-1\)......
  • 题解:CF634A Island Puzzle
    CF634AIslandPuzzle题解分析由于我们仅能移动\(0\),所以其它数字的相对顺序较原来应该是不变的,所以我们从环中删除\(0\)再判断相对位置即可。还有需要注意的是本题是一个环,找到末尾需要用取模操作回到开头继续比较。示例代码#include<bits/stdc++.h>usingnamespacest......
  • 题解:CF718A Efim and Strange Grade
    CF718AEfimandStrangeGrade题解算法贪心+模拟思路分析显然,要最优每一次进位就只能五入不能四舍。而且当我们五入时,要取位数最高的。比如说\(1.3535\),我们有两种进位方式,一种是进位成\(1.4\),一种是进位成\(1.354\),显然前者更优。那这道题给的次数有啥用呢?考虑一种“......
  • 题解:CF1301D Time to Run
    CF1301DTimetoRun题解思维题。分析把一个格子视作一个点,每个点的度数都是偶数,所以这是一张欧拉图。而需要走遍整个方格图,可以证明只要\(k\)不超过\(4nm-2n-2m\)就一定有解。很明显存在很多种方案,这里我用的方案是:从左上角出发,向右走\(m-1\)步到头,再向左走\(m-1\)......
  • 题解:CF771A Bear and Friendship Condition
    CF771ABearandFriendshipCondition题解算法并查集,图的基本性质分析题目意思是,一旦有一些点联通,那么这些点必须两两直接相连。换句话讲,就是图中的每个联通块都是完全图。所谓完全图,就是图中的每个点都两两相连,假设一个完全图有\(n\)个点,那么我们可以通过乘法原理算出这......