#include <bits/stdc++.h>
using namespace std;
const int mn = 10010;
int cnt;
int to[2 * mn], nx[2 * mn], fr[mn];
void add_edge(int u, int v)
{
to[cnt] = v;
nx[cnt] = fr[u];
fr[u] = cnt++;
}
int n;
int pans, ans1;
bool vis[mn];
int dfs(int u)
{
vis[u] = 1;
int tol = 0;
int sum = 0;
for (int i = fr[u]; i != -1; i = nx[i])
{
if (!vis[to[i]])
{
int t = dfs(to[i]);
tol += t;
sum += t * (n - t); // 子节点间点对数重复计算
}
}
// tol 叶子连通块节点总数
sum += tol * (n - tol); // 子节点与其他节点点对数重复计算
sum /= 2;
if (ans1 < sum)
{
ans1 = sum;
pans = u;
}
return tol + 1;
}
int dfs2(int u)
{
vis[u] = 1;
int tol = 0;
for (int i = fr[u]; i != -1; i = nx[i])
{
if (!vis[to[i]])
tol += dfs2(to[i]);
}
return tol + 1;
}
int main()
{
memset(fr, -1, sizeof fr);
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
int a, b;
scanf("%d %d", &a, &b);
add_edge(a, b);
add_edge(b, a);
}
dfs(0);
memset(vis, 0, sizeof vis);
vis[pans] = 1;
int ma1 = 0, ma2 = 0;
for (int i = fr[pans]; i != -1; i = nx[i]) // 每个子节点连通块上的点数
{
int t = dfs2(to[i]);
if (t > ma1)
{
ma2 = ma1;
ma1 = t;
}
else if (t > ma2)
ma2 = t;
}
printf("%d %d\n", ans1, ans1 - ma1 * ma2);
return 0;
}
[DFS] 树上删点使两连通块构成的点对最少 CFgym/101673F
猜你喜欢
转载自blog.csdn.net/ummmmm/article/details/83626118
今日推荐
周排行