题意:对于一棵给定的树要使得删除一条边的两个连通块不相等,此时该边的连接的两个点为树的重心
思路:由于重心有两个对树的每一个节点作为一个节点找到删除一个节点,最大连通块最小的两个节点,将其中一个节点的一个连通块连接另一个连通块即可(树的重心模板)
AC代码 :
package 练习;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;
public class M {
static Scanner in = new Scanner(System.in);
static int[] visited;
static int c = Integer.MAX_VALUE;
static int c1 = 0;
static int c2 = 0;
public static void main(String[] args) {
int t = in.nextInt();
while(t-- > 0) {
c = Integer.MAX_VALUE;
c1 = 0;
c2 = 0;
int n = in.nextInt();//n个点
ArrayList<Integer>[] tree = new ArrayList[n + 1];
for(int i = 0; i < n - 1; i++) {//n-1条边
int a = in.nextInt();
int b = in.nextInt();
if (tree[a] == null) {
tree[a] = new ArrayList<Integer>();
}
if (tree[b] == null) {
tree[b] = new ArrayList<Integer>();
}
tree[a].add(b);
tree[b].add(a);
}
visited = new int[n+1];
dfs(tree,1,n);
if(c2 == 0) {
System.out.println("1 " + tree[1].get(0));
System.out.println("1 " + tree[1].get(0));
}else {
for(int x : tree[c2]) {
if(x != c1) {
System.out.println(c2 + " " + x);
System.out.println(c1 + " " + x);
break;
}
}
}
}
}
public static int dfs(ArrayList<Integer>[] tree, int root, int n) {
visited[root] = 1;//判断root点是否已经判断过
int count = 1;//
int maxc = 0;
if(tree[root] != null) {
for(int x : tree[root]) {//搜索各个分支
if(visited[x] == 0) {
int curr = dfs(tree, x, n);
maxc = Math.max(maxc, curr);
count += curr;
}
}
}
int r = n - count;
int max = Math.max(r, maxc);
if(max < c) {//判断删除root最大块的是否小于c
c = max;
c1 = root;
c2 = 0;
}else if(max == c) {//肯定会出现,只有偶数节点的时候才执行代码
c2 = root;
}
return count;
}
}