Tree split (cut)

Description


There is an unrooted tree with (n) nodes, each node is numbered (1 sim n). Now it is required to delete one of the nodes so that the number of nodes in each subtree part that is divided does not exceed (n/2).

Format


Input

The first line is a positive integer (t(≤5)), indicating the number of test data groups; in each group of data, the first line is a positive integer (n(≤10^5)), and the next (n-1) lines have two positive integers (x) and (y) ((x, y≤n)), respectively represent the two node numbers connecting the edges.

Output

For each group of data, output the number of the split point. If there are more than one node, output in the order from smallest to largest; if not, output "None".

Sample


Input

2
10
1 2
2 3
3 4
4 5
6 7
7 8
8 9
9 10
3 8
5
1 5
5 2
3 4
4 1

Output

3 8
1

Sample Explanation

The tree of sample 1 is shown in the figure below, and nodes 3 and 8 meet the conditions:
pic

Sample Code


#include <cstdio>
#include <cstring>
const int N=100010;
struct Edge{
    int v, next;
}edge[2*N]; 
struct Head{
    int deg, mmax, first;
}head[N];//deg记录以当前点为根的子树总结点数(度),mmax记录其子树中度的最大值 
int now, n;
bool vis[N];

void in(int &s){
	char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	for (s=0; c>='0' && c<='9'; c=getchar())
		s=s*10+c-'0';
}
inline int mx(int a, int b){
	return a>b ? a : b;
}
void ins(int x, int y){
	now++; edge[now].v=y; 
	edge[now].next=head[x].first; head[x].first=now;
}//头插法建立链式前向星 

void dfs(int r){
    vis[r]=1;
    int deg=1, tp=0;
    for (int k=head[r].first; k; k=edge[k].next){
        int v=edge[k].v;
        if (!vis[v]){
            dfs(v);
            if (head[v].deg > tp) 
                tp=head[v].deg;
            deg+=head[v].deg;
        }
    }
    head[r].deg=deg;//记录当前子树的总结点数(度) 
    head[r].mmax=mx(tp, n-deg);//记录所有子树中的最大度 
}
int main(){
    freopen("cut.in", "r", stdin);
    freopen("cut.out", "w", stdout);
    int t;
    scanf("%d", &t);
    while (t--){
		scanf("%d", &n);
        memset(vis, 0, sizeof(vis));
        memset(head, 0, sizeof(head));
		int x, y;
        now=0;
        for (int i=1; i<n; i++){
            in(x), in(y);//scanf("%d %d", &x, &y); 
            ins(x, y); ins(y, x);
        }
        dfs(1); 
		bool ok=false;
        for (int i=1; i<=n; i++)
            //if (n-head[i].deg <= n/2 && head[i].mmax <= n/2){
			if (head[i].mmax <= n/2){
                printf("%d ", i); ok=true;
            }//n-head[i].deg表示除去当前子树外其他所有结点总数(恰好构成另一个方向的子树) 
        if (!ok) printf("None");
        printf("
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jiupinzhimaguan/p/13806447.html