| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 9143 | Accepted: 3797 |
Description

Input
Output
Sample Input
1 7 2 6 1 2 1 4 4 5 3 7 3 1
Sample Output
1 2
Source
/*
定义dp[i]为去掉i结点,剩下的树里,结点最多的那颗树的结点数。
可分为2类情况。
1、由于i结点的儿子结点都成了一棵树的根节点,所以dp[i] = (i的每个儿子所拥有的结点数,的最大值)。
2、而另一种情况就是剩下的那棵树,所以dp[i] = N-num[i]。
其中num[i]表示以i为根的树的所有结点数,可以dfs求出。
*/
#include <map>
#include <set>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 20010;
const int inf = 0x3f3f3f3f;
int n;
struct node
{
int next;
int to;
}edge[N << 1];
int head[N];
int dp[N];
int num[N];
int tot;
bool vis[N];
int dist[N];
void addedge(int from, int to)
{
edge[tot].to = to;
edge[tot].next = head[from];
head[from] = tot++;
}
int dfs(int u)
{
vis[u] = 1;
num[u] = 1;
for (int i = head[u]; ~i; i = edge[i].next)
{
int v = edge[i].to;
if (!vis[v])
{
num[u] += dfs(v);
}
}
return num[u];
}
void DP(int u)
{
vis[u] = 1;
for (int i = head[u]; ~i; i = edge[i].next)
{
int v = edge[i].to;
if (vis[v])
{
dp[u] = max(dp[u], n - num[u]);
}
else
{
dp[u] = max(dp[u], num[v]);
DP(v);
}
}
}
int main()
{
int t;
int u, v;
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
memset ( head, -1, sizeof(head) );
memset ( num, 0, sizeof(num) );
memset ( vis, 0, sizeof(vis) );
memset ( dp, 0, sizeof(dp) );
tot = 0;
for (int i = 0; i < n - 1; ++i)
{
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
dfs(1);
memset ( vis, 0, sizeof(vis) );
DP(1);
int ans = inf, id;
for (int i = 1; i <= n; ++i)
{
if (ans > dp[i])
{
ans = dp[i];
id = i;
}
}
printf("%d %d\n", id, ans);
}
return 0;
}原文地址:http://blog.csdn.net/guard_mine/article/details/40738579