现在有 105 个用户,编号为 1- 105,现在已知有 m 对关系,每一对关系给你两个数 x 和 y ,代表编号为 x 的用户和编号为 y 的用户是在一个圈子中,例如: A 和 B 在一个圈子中, B 和 C 在一个圈子中,那么 A , B , C 就在一个圈子中。现在想知道最多的一个圈子内有多少个用户。
数据范围: 
进阶:空间复杂度
,时间复杂度 %20%5C)
进阶:空间复杂度
第一行输入一个整数T,接下来有T组测试数据。
对于每一组测试数据:第一行输入1个整数n,代表有n对关系。接下来n行,每一行输入两个数x和y,代表编号为x和编号为y的用户在同一个圈子里。1 ≤ T ≤ 101 ≤ n ≤ 2*1061 ≤ x, y ≤ 105
对于每组数据,输出一个答案代表一个圈子内的最多人数
2 4 1 2 3 4 5 6 1 6 4 1 2 3 4 5 6 7 8
4 2
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
class UnionFind {
public static int[] parent = new int[10000001];
public static int[] personNums = new int[10000001];
public UnionFind(){
for(int i = 1; i <= 10000000; i++){
parent[i] = i;
personNums[i] = 1;
}
}
public int find(int x) {
while(x != parent[x]){
parent[x] = parent[parent[x]]; // 路径压缩
x = parent[x];
}
return x;
}
public void union(int x, int y){
int rootX = find(x);
int rootY = find(y);
if(rootX == rootY) return;
parent[rootY] = rootX;
personNums[rootX] += personNums[rootY];
}
}
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
while(T -- > 0){
int n = Integer.parseInt(br.readLine());
UnionFind uf = new UnionFind();
for(int i = 0; i < n; i++){
String[] params = br.readLine().trim().split(" ");
int x = Integer.parseInt(params[0]);
int y = Integer.parseInt(params[1]);
uf.union(x, y);
}
int max = 0;
for(int i = 1; i < uf.personNums.length; i++)
max = Math.max(max, uf.personNums[i]);
System.out.println(max);
}
}
} #include <iostream>
#include <unordered_map>
using namespace std;
unordered_map<int, int> fa; //用fa来存储父节点
unordered_map<int, int> cnt; //用cnt来存储节点的子节点数量
int find(int x) //寻找父节点
{
if (fa.find(x) == fa.end()) { //fa[x]尚未存在表中时
fa[x] = x; //将fa[x]的父节点设置为自己
cnt[x] = 0;
}
if (x == fa[x]) {
return x;
}
return fa[x] = find(fa[x]); //将x的根节点设置为父节点(路径压缩),并返回根节点
}
void Union(int x, int y) //合并
{
int fx = find(x); //fx为x的父节点
int fy = find(y); //fy为y的父节点
fa[fx] = fy; //将fx的父节点设为fy
}
int main()
{
int T;
cin >> T;
while (T--)
{
int n;
cin >> n;
while (n--)
{
int x, y;
cin >> x >> y;
Union(x, y);
}
int ans = 0; //每个节点子节点数至少为1(其自身),故将初始ans设置为0用于后续比较
for (unordered_map<int,int>::iterator it=fa.begin();it!=fa.end(); it++)
{
int fi = find(it->second);
cnt[fi]++; //每到节点i就往其根节点cnt[]+1
if (cnt[fi] > ans)
ans = cnt[fi];
}
cout << ans << endl;
fa.clear();
cnt.clear();
}
return 0;
}
// 邻接表 + dfs
#include<iostream>
#include<vector>
using namespace std;
int cnt,ans;
int v[100001];
vector<int>a[100001];
void dfs(int x)
{
int i,num;
v[x]=1; cnt++;
for(i=0;i<a[x].size();i++)
{
num=a[x][i];
if(v[num]==0)dfs(num);
}
}
int main()
{
int i,k,n,x,y,T;
scanf("%d",&T);
for(i=0;i<T;i++)
{
scanf("%d",&n);
for(k=1;k<=1e5;k++)
{
v[k]=0;
a[k].clear();
}
for(k=1;k<=n;k++)
{
scanf("%d %d",&x,&y);
a[x].push_back(y);
a[y].push_back(x);
}
ans=0;
for(k=1;k<=1e5;k++)
{
cnt=0;
dfs(k);
ans=max(ans,cnt);
}
printf("%d\n",ans);
}
return 0;
}
使用并查集,并添加路径压缩。关于并查集和路径压缩的讲解见并查集
详细注释代码如下:
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt(); // t组数据
for (int i = 0; i < t; i++) {
int n = sc.nextInt(); // n对关系
HashMap<Integer,Integer> map = new HashMap<>(); // 用户数字 到 数组位置 的映射
int[] check = new int[n * 2]; // 并查集数组(n对,最多 n * 2 个用户)
for (int j = 0; j < n * 2; j++) { // 初始化并查集,指向自己
check[j] = j;
}
for (int j = 0; j < n; j++) { // 建立并查集
int a = sc.nextInt(); // 读入用户对
int b = sc.nextInt();
int x = map.getOrDefault(a, map.size()); // 找到映射
map.put(a, x);
int y = map.getOrDefault(b, map.size());
map.put(b, y);
if (find(check, x) != x && find(check, y) != y) { // 当都有根,从根部联通两并查集,能减少find的次数
check[find(check, x)] = find(check, y); // (连接方式未优化)
} else if (find(check, x) != x) { // 只有一方有根,另一方直接连到根;都没根时一样
check[y] = find(check, x);
} else {
check[x] = find(check, y);
}
}
HashMap<Integer,Integer> res = new HashMap<>(); // 并查集根 和 并查集节点个数 的映射
for (int j = 0; j < n * 2; j++) { // 遍历并查集
int k = find(check, j); // 找到当前节点的根
res.put(k, res.getOrDefault(k, 0) + 1); // 节点个数加一
}
int max = 0;
for (Integer value : res.values()) { // 遍历各个并查集的节点个数,找出最大者
max = Math.max(max, value);
}
System.out.println(max); // 打印
}
}
// 查找并查集的根
private static int find(int[] check, Integer i) {
if (check[i] != i) { // 当前节点非根
check[i] = find(check, check[i]); // 当前节点指向根(路径压缩)
}
return check[i]; // 返回根
}
}
"""使用并查集解题"""
""" 运行时间: 2834ms
占用内存: 14236KB """
class UnionFind():
def __init__(self, **kwargs):
"""构造函数"""
self.fa = [i for i in range(int(1e5+1))] #存储每个数据的根节点
self.num = [1] * int(1e5+1) #存储根节点的子节点数目
self.max_num = 1
def find(self, p):
"""查找根节点"""
if self.fa[p] == p:
return p
self.fa[p] = self.find(self.fa[p])#把父节点的根节点当作父节点
return self.fa[p] #返回父节点,此时父节点就是根节点
def merge(self, p, q):
"""连通p,q 让q指向p"""
proot = self.find(p)
qroot = self.find(q)
if proot != qroot:
self.fa[qroot] = proot
self.num[proot] += self.num[qroot]
self.max_num = max(self.max_num, self.num[proot])
def get_max(self):
return self.max_num
def reset(self):
self.fa = [i for i in range(int(1e5+1))]
self.num = [1] * int(1e5+1)
self.max_num = 1
T = int(input().strip())
UF = UnionFind()
for i in range(T):
# print(f'第{i+1}组测试数据')
UF.reset()
n = int(input().strip())
ii = 0
while ii < n:
p, q = map(int, input().split())
UF.merge(p, q)
ii += 1
print(UF.get_max())
importjava.util.*;
importjava.io.*;
importjava.lang.Math;
public class Main {
public static void main(String[] args) {
Scanner cin=new Scanner(new BufferedInputStream(System.in));
int t=cin.nextInt();
int[] res=new int[t];
for (int i = 0; i < t; ++i) {
int n = cin.nextInt();
int[][] relationships = new int[n][2];
Set<Integer> UFS=new HashSet<>(); //收集这一组中出现过的元素,用于下面建立并查集
for (int j = 0; j < n; ++j) { //自定义格式化每一组的关系
relationships[j][0] = cin.nextInt();
relationships[j][1] = cin.nextInt();
UFS.add(relationships[j][0]);
UFS.add(relationships[j][1]);
}
res[i]=maxCircle(relationships,UFS); //计算这一组中最大圈子的数量
}
for (int re : res) {
System.out.println(re);
}
cin.close();
}
private static int maxCircle(int[][] relationships,Set<Integer> UFS) {
Map<Integer,Integer> ufs=new HashMap<>();
for (Integer uf : UFS) //初始化并查集
ufs.put(uf,-1);
for (int[] relationship : relationships)
ufsUnion(ufs,relationship[0],relationship[1]); //根据关系调整并查集
int min = 0;
for (Integer uf : UFS)
min=Math.min(ufs.get(uf),min);
return (-1)*min;
}
private static void ufsUnion(Map<Integer, Integer> ufs, int a, int b) {
int root1=ufsFind(ufs,a);
int root2=ufsFind(ufs,b);
if (root1==root2) return;
int temp1=ufs.get(root1);
int temp2=ufs.get(root2);
//路径压缩,让小树并到大树下,尽量减少树的高度
if (temp1<temp2) {
ufs.put(root2,root1);
ufs.put(root1,temp1+temp2);
}
else {
ufs.put(root1,root2);
ufs.put(root2,temp1+temp2);
}
}
private static int ufsFind(Map<Integer,Integer> ufs,int a) {
int temp=a;
while (ufs.get(temp)>0)
temp=ufs.get(temp);
return temp;
}
} #include <bits/stdc++.h>
using namespace std;
int total_t, n;
int NumofLargestGroup(vector<int>* mat, int n)
{
if(!n)
return n;
vector<bool> visited(10000005, false);
int ans = 0;
stack<int> s;
for(int i = 1; i <= 10000000; ++i)
{
if(visited[i] || mat[i].empty())
continue;
s.push(i);
int cur_ans = 0;
while(!s.empty())
{
int cur = s.top();
s.pop();
if(visited[cur])
continue;
visited[cur] = true;
++cur_ans;
for(const auto& fr : mat[cur])
{
//cout << "cur " << cur <<" fr " << fr << endl;
if(visited[fr])
continue;
s.push(fr);
}
}
ans = max(ans, cur_ans);
}
return ans;
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0);
cin >> total_t;
while(total_t--)
{
vector<int> mat[10000005];
cin >> n;
int a, b;
for(int i = 1; i <= n; ++i)
{
cin >> a >> b;
mat[a].push_back(b);
mat[b].push_back(a);
}
cout << NumofLargestGroup(mat, n) << endl;
}
} public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int graph_nums = sc.nextInt();
int T = 0;
while (T < graph_nums){
LinkedHashSet<edge> edges = new LinkedHashSet<>();
int edges_nums = sc.nextInt();
for (int i = 0; i < edges_nums; i++) {
edge edge = new edge(sc.nextInt(),sc.nextInt());
edges.add(edge);
}
int pyq = pyq(edges);
System.out.println(pyq);
T++;
}
sc.close();
}
//求最大连通分量
public static int pyq(LinkedHashSet<edge> edges){
// 1. 构建邻接表
Map<Integer, List<Integer>> adjacencyList = new HashMap<>();
for (edge e : edges) {
adjacencyList.putIfAbsent(e.node1, new ArrayList<>());
adjacencyList.putIfAbsent(e.node2, new ArrayList<>());
adjacencyList.get(e.node1).add(e.node2);
adjacencyList.get(e.node2).add(e.node1);
}
// 2. 遍历每个连通分量,记录最大值
int maxComponentSize = 0;
Set<Integer> visited = new HashSet<>();
for (int node : adjacencyList.keySet()) {
if (!visited.contains(node)) {
int componentSize = dfs(adjacencyList, node, visited);
maxComponentSize = Math.max(maxComponentSize, componentSize);
}
}
return maxComponentSize;
}
private static int dfs(Map<Integer, List<Integer>> adjacencyList, int node, Set<Integer> visited) {
visited.add(node);
int componentSize = 1;
for (int neighbor : adjacencyList.getOrDefault(node, new ArrayList<>())) {
if (!visited.contains(neighbor)) {
componentSize += dfs(adjacencyList, neighbor, visited);
}
}
return componentSize;
}
}
class edge{
int node1,node2;
edge(int node1,int node2){
this.node1 = node1;
this.node2 = node2;
}
public boolean equals(edge e) {
if ((e.node1 == this.node1 && e.node2 == this.node2) ||
(e.node1 == this.node2 && e.node2 == this.node1)){
return true;
}
return false;
}
} 可以使用并查集(Union-Find)来解决此问题。首先将所有用户看作一个单独的圈子,然后遍历所有关系对,将它们所在的圈子合并起来。最终,统计每个圈子的大小并找到最大值即可。
以下是Python代码的示例实现:
class UnionFind: def __init__(self, n): self.parent = list(range(n)) self.size = [1] * n def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): root_x, root_y = self.find(x), self.find(y) if root_x == root_y: return if self.size[root_x] < self.size[root_y]: root_x, root_y = root_y, root_x self.parent[root_y] = root_x self.size[root_x] += self.size[root_y] def max_circle(m): uf = UnionFind(105) for x, y in m: uf.union(x-1, y-1) return max(uf.size) # Example usage: m = [(1, 2), (2, 3), (4, 5), (6, 7), (7, 8), (9, 10), (100, 101)] max_size = max_circle(m) print(max_size) # Output: 4
其中,UnionFind类实现了并查集,其中parent数组用于记录每个节点的父节点,size数组用于记录每个圈子的大小。find方法实现了路径压缩,使查找操作的时间复杂度接近常数。union方法实现了按秩合并和路径压缩,使合并操作的时间复杂度接近常数。
max_circle函数使用UnionFind类来处理关系对,然后找到最大圈子的大小并返回。
================================#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX_N = 1e5 + 5;
int parent[MAX_N];
int sz[MAX_N];
int find(int x) {
if (x == parent[x]) {
return x;
}
parent[x] = find(parent[x]);
return parent[x];
}
void merge(int x, int y) {
int px = find(x);
int py = find(y);
if (px == py) {
return;
}
parent[py] = px;
sz[px] += sz[py];
}
int main() {
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int t;
cin >> t;
while (t--) {
int m;
cin >> m;
unordered_set<int> set;
for (int i = 0; i < MAX_N; i++) {
sz[i] = 1;
parent[i] = i;
}
for (int i = 0; i < m; i++) {
int x, y;
cin >> x >> y;
set.insert(x);
set.insert(y);
merge(x, y);
}
int ans = 0;
for (auto x : set) {
ans = max(ans, sz[find(x)]);
}
cout << ans << endl;
}
return 0;
}
#参考https://oi-wiki.org/ds/dsu/ class Dsu: def __init__(self,size): self.pa = list(range(size)) self.size = [1]*size self.max_size=1 def find(self,x): #沿着树向上找到x的根节点,并将查询过程中经过的每个元素都归到根节点(路径压缩) if self.pa[x]!=x: self.pa[x] = self.find(self.pa[x]) return self.pa[x] def union(self,x,y):# 将x的根节点接到y, #启发式合并,将小的树合并到大的树 x,y = self.find(x),self.find(y) if x==y: return if self.size[x]<self.size[y]: x,y=y,x self.pa[y]=x self.size[x]+=self.size[y] if self.size[x]>self.max_size: self.max_size=self.size[x] while True: try: T=int(input()) for _ in range(T): n = int(input()) dsu = Dsu(100000+1) for _ in range(n): x,y=list(map(int,input().split())) dsu.union(x,y) print(dsu.max_size) del dsu except: break
# 深度优先算法
t=int(input())
from collections import defaultdict
import sys # 导入sys模块
sys.setrecursionlimit(30000)
def rec(num):
if dic.get(num):
return dic.get(num)
visitd.add(num)
find_count=1
for p in edge[num]:
if p not in visitd:
find_count+=rec(p)
dic[num]=find_count
return dic[num]
for i in range(t):
edge=defaultdict(list)
n,nums,dic=int(input()),set(),{}
for j in range(n):
x,y=[m for m in input().split()]
nums.add(x)
nums.add(y)
edge[x].append(y)
edge[y].append(x)
visitd,max_count=set(),2
for q in nums:
if q not in visitd and (len(nums)-len(visitd))>max_count:
tem=rec(q)
max_count=max(max_count,tem)
print(max_count)
#广度优先算法
t=int(input())
from collections import defaultdict
for i in range(t):
edge,max_count=defaultdict(list),2
n,nums,visited=int(input()),set(),set()
for j in range(n):
x,y=[m for m in input().split()]
nums.add(x)
nums.add(y)
edge[x].append(y)
edge[y].append(x)
for i in nums:
if i not in visited:
count,stack=1,[i]
visited.add(i)
while stack:
cur=stack.pop()
for j in edge[cur]:
if j not in visited:
visited.add(j)
stack.append(j)
count+=1
max_count=max(max_count,count)
print(max_count) import java.util.*;
public class Main {
/*
整体背景就是一堆孩子 认爹
然后看哪个爹孩子最多(还要加上老爹)
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
//一共几组数据
for (int i = 0; i < n; i++) {
//找自己的爹节点 如果parent中不存在自己 那么说明自己没有爹节点
//自己就是自己的爹
Map<Integer, Integer> parent = new HashMap<Integer, Integer>();
//哪个爹有多少个孩子 key是爹 value是孩子的数量
Map<Integer, Integer> sizeMap = new HashMap<Integer, Integer>();
int m = sc.nextInt();
for (int j = 0; j < m; j++) {
int a = sc.nextInt();
int b = sc.nextInt();
//分别找爹 看看谁的爹大
int pa= find(parent,a);
int pb= find(parent,b);
//如果你爹不等于我爹
if (pa!=pb){
//那么你pb要认我为爹
parent.put(pb, pa);
//你pb家族的孩子都归我们家族了
int pbSize = sizeMap.getOrDefault(pb, 1);
int paSize = sizeMap.getOrDefault(pa, 1);
sizeMap.put(pa,paSize+pbSize);
//pb家族从此除根
sizeMap.remove(pb);
}
}
//找哪个家族最庞大 孩子最多 基本就是一map遍历过程
Iterator<Map.Entry<Integer, Integer>> it = sizeMap.entrySet().iterator();
int res=1;
while (it.hasNext()){
res=Math.max(res,it.next().getValue());
}
System.out.println(res);
}
}
//找爹的函数 这里必须扁平化 否则时间过不了
//解释一下扁平化 就是说1是2爹 2是3爹
//这样3要找爹的话 肯定3->2 2->1 分两步
//如果链子很长就不行了 所以现在要乱辈 大家都认一个最大是爹 剩下都是孩子
//可以想象优化后就是一个N叉树 就两层的 根节点是爹 剩下一排孩子
private static int find(Map<Integer, Integer> parent, int i) {
//保存沿途想认最大的爹为爹的孩子节点
Stack<Integer> s=new Stack<>();
//循环 只要我还能找到爹 就继续往下找
while (parent.containsKey(i)){
s.push(i);
i=parent.get(i);
}
//扁平化
while (!s.isEmpty()){
parent.put(s.pop(),i);
}
//返回家族最大的爹
return i;
}
} 简单并查集模型
#include <iostream>
const int M = 2000010,N = 100010;
using namespace std;
int t;
int p[N];
int sum[N];
int find(int x)
{
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i = 1;i <= N;i++)
{
p[i] = i;
sum[i] = 1;
}
int res = 0;
while(n--)
{
int x,y;
scanf("%d%d",&x,&y);
int px = find(x),py = find(y);
if(px != py)
{
p[px] = py;
sum[py] += sum[px];
}
res = max(res,sum[py]);
}
printf("%d\n",res);
}
return 0;
}
用了并查集模板就是舒服
import java.util.*;
public class Main{
static int N = 100010; // 习惯了超出10个
static int[] p = new int[N + 1]; // 每个用户的父节点
static int[] size = new int[N + 1]; // 只保证根节点的数量正确有效即可
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
for (int k = 0; k < T; k++) {
// 每次都初始化所有用户(因为题目给了 T 组测试数据)
for (int i = 1; i <= N; i++) {
p[i] = i;
size[i] = 1;
}
int n = sc.nextInt();
// n对关系
for (int i = 0; i < n; i++) {
int x = sc.nextInt();
int y = sc.nextInt();
if(find(x) == find(y)) continue; // 不能重复挂
// x挂到y上 之前,先统计x、y两个集合人数,再把x挂到y
size[find(y)] += size[find(x)]; //先统计两个集合点数
p[find(x)] = find(y); // 把x挂到y的根节点上
}
// 统计那个最大朋友圈的用户数
int res = 0;
for (int i : size) {
res = Math.max(res, i);
}
System.out.println(res);
}
}
// 找出x的根节点(带路径压缩)
public static int find(int x) {
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
}
n=100001 T=int(input()) #寻找根节点 def getFather(x): a=x while father[x]!=x: x=father[x] #路径压缩 while father[a]!=a: z=a a=father[a] father[z]=x return x for _ in range(T): #初始化 father = [i for i in range(n)] isroot=[0]*(n) m=int(input()) for _ in range(m): i,j=map(int,input().strip().split()) if getFather(i)!=getFather(j): i=getFather(i) j=getFather(j) father[j]=i res=1 for i in range(1,n): isroot[getFather(i)]+=1 res=max(res,isroot[getFather(i)]) print(res)
#include<bits/stdc++.h>
using namespace std;
unordered_map<int, int>fa;
unordered_map<int, int>cnt;
int find(int x){
if(fa.find(x)==fa.end()){
fa[x]=x;
cnt[x]=0;
}
if(x==fa[x]){
return x;
}
return fa[x]=find(fa[x]);
}
void Union(int x,int y){
int fx=find(x);
int fy=find(y);
fa[fx]=fy;
}
int main(){
int T;cin>>T;
while(T-- >0){
int n;cin>>n;
while(n-- >0){
int x,y;
cin>>x>>y;
Union(x,y);
}
int ans=0;
for(unordered_map<int, int>::iterator it=fa.begin();it!=fa.end();it++){
int fi=find(it->second);
cnt[fi]++;
ans=max(ans,cnt[fi]);
}
cout<<ans<<endl;
fa.clear();
cnt.clear();
}
} using namespace std;
#include<iostream>
#include<algorithm>
#include<numeric>
#include<vector>
//#include<bits/stdc++.h>
vector<int>id(100001, 0);
vector<int>counts(100001, 1);
int maxrs = 0;
int find(int x) { while (x!=id[x]) { id[x] = id[id[x]]; x = id[x]; } return x;
}
void unionxy(int x, int y) { x = find(x); y = find(y); if (x != y) { if (counts[x] > counts[y]) { counts[x] += counts[y]; counts[y] = 0; id[y] = id[x]; if (maxrs < counts[x]) maxrs = counts[x]; } else { counts[y] += counts[x]; counts[x] = 0; id[x] = id[y]; if (maxrs < counts[y]) maxrs = counts[y]; } } }
int main() { int T; cin >> T; while (T--) { int n; cin >> n; iota(id.begin(), id.end(), 0); fill(counts.begin(), counts.end(), 1); maxrs = 0; for (int i = 0; i < n; i++) { int x, y; cin >> x >> y; unionxy(x, y); } cout << maxrs << endl; } return 0;
}
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;
int deep(int key, unordered_map<int, vector<int>> &mp, unordered_map<int, int> &visit){
vector<int> tmp = mp[key];//访问当前节点是否有其他子节点
visit[key] = 1;//并且标志这个节点已经访问过了
int d = 1;//然后 深度 加1
for(auto t:tmp){
if(!visit[t])//如果没有访问
d += deep(t,mp,visit);//那么当前节点就加上 子节点的深度
}
return d;//返回当前节点的深度
}
void func(unordered_map<int, vector<int>> &mp){
int ans = 0;
unordered_map<int, int> visit;
for(auto [key, vval]:mp){
if(!visit[key]){//如果这个节点没有访问过,那么这个节点连接的树就是一棵独立的树
ans = max(ans, deep(key, mp, visit));//求最大深度
}
}
cout<<ans<<endl;
}
int main(){
std::ios::sync_with_stdio(0);
cin.tie(0);//加快输入
int T;
cin>>T;
while(T--){
int n;
cin>>n;
int x,y;
unordered_map<int, vector<int>> mp;
for(int i = 0; i < n; i++){
cin>>x>>y;
mp[x].emplace_back(y);//由单向图建立双向图
mp[y].emplace_back(x);
}
func(mp);
}
return 0;
}