Balancing Act
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 7868 | Accepted: 3216 |
Description
Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or more trees. Define the balance of a node to be the size of the largest tree in the forest T created by deleting that node from T.
For example, consider the tree:
Deleting node 4 yields two trees whose member nodes are {5} and {1,2,3,6,7}. The larger of these two trees has five nodes, thus the balance of node 4 is five. Deleting node 1 yields a forest of three trees of equal size: {2,6}, {3,7}, and {4,5}. Each of these trees has two nodes, so the balance of node 1 is two.
For each input tree, calculate the node that has the minimum balance. If multiple nodes have equal balance, output the one with the lowest number.
For example, consider the tree:
Deleting node 4 yields two trees whose member nodes are {5} and {1,2,3,6,7}. The larger of these two trees has five nodes, thus the balance of node 4 is five. Deleting node 1 yields a forest of three trees of equal size: {2,6}, {3,7}, and {4,5}. Each of these trees has two nodes, so the balance of node 1 is two.
For each input tree, calculate the node that has the minimum balance. If multiple nodes have equal balance, output the one with the lowest number.
Input
The first line of input contains a single integer t (1 <= t <= 20), the number of test cases. The first line of each test case contains an integer N (1 <= N <= 20,000), the number of congruence. The next N-1 lines each contains two space-separated node numbers that are the endpoints of an edge in the tree. No edge will be listed twice, and all edges will be listed.
Output
For each test case, print a line containing two integers, the number of the node with minimum balance and the balance of that node.
Sample Input
1 7 2 6 1 2 1 4 4 5 3 7 3 1
Sample Output
1 2
Source
此题要求我们求一棵树的重心。
给定一棵N个结点的树,求该树的所有重心。重心的定义如下:
删掉某结点i后,若剩余k个连通分量,那么定义d(i)为这些连通分量中结点数的最大值。
所谓重心,就是使得d(i)最小的结点i。
算法分析:
建图;
树的基本操作:以结点1为根,计算出每个结点所在的子树的结点数。
枚举每一个结点,若将其删掉,那么考虑剩余的所有连通分量。
1、它的子树,其结点数可以直接调用。
2、它的上方子树,其结点数可通过n-1-减去所有子树的结点数算出。
这样,在其中选择d(i)最小的即可。时间复杂度:O(N),空间复杂度:O(N)
/**********************
* author:crazy_石头
* Pro:POJ 1655 Balancing Act(求树的重心)
* algorithm:dfs
* Time:31ms
* Judge Status:Accepted
***********************/
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
using namespace std;
#define rep(i,h,n) for(int i=(h);i<=(n);i++)
#define ms(a,b) memset((a),(b),sizeof(a))
#define eps 1e-6
#define INF 1<<29
#define LL __int64
const int maxn=20000+5;
const int maxm=200+10;
int dp[maxn],num[maxn],vis[maxn];
struct Edge
{
int to,next;
}edge[maxn<<1];
int head[maxn];
int cnt,n,m;
inline void addedge(int u,int v)
{
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
inline void add(int u,int v)
{
addedge(u,v);
addedge(v,u);
}
inline void init()
{
cnt=0,ms(head,-1);
}
inline void dfs(int u,int father)
{
dp[u]=0,num[u]=1,vis[u]=1;
for(int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].to;
if(v==father)continue;
if(!vis[v])
{
dfs(v,u);
dp[u]=max(dp[u],num[v]);
num[u]+=num[v];
}
}
dp[u]=max(dp[u],n-num[u]);
}
int main()
{
int test;
cin>>test;
while(test--)
{
cin>>n;
init(),ms(vis,0);
rep(i,1,n-1)
{
int u,v;
cin>>u>>v;
add(u,v);
}
dfs(1,-1);
int index=1,ret=dp[1];
rep(i,2,n)
{
if(ret>dp[i])
{
ret=dp[i];
index=i;
}
}
cout<<index<<" "<<ret<<endl;
}
return 0;
}