NC201400 树学
题目链接
关键点:
1、w值即为所有点的深度和,那么假如我们将一个点作为根节点,那么该点的深度和 - 该点孩子的深度(该点所有的孩子深度都-1) + 该点父亲的结点深度(该点所有祖先结点深度+1)
2、首先求出所有点的深度,和以1(任意一个结点)的深度和,这些可以用一个dfs解决
3、然后是求出所有以所有点为根节点的总深度和,再用类似的dfs可以解决
4、答案是所有结点为根节点的总深度的最小值
完整代码:
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dep[1000000+10];//当前点的深度
ll cnt[1000000+10];//当前点的孩子的总深度,包括自己
ll f[1000000+10];//以i为结点的总深度和
int sum, n;
vector<int> ve[1000000+10];
void dfs1(int x, int fa)
{
cnt[x] = 1;
for (int i=0; i<ve[x].size(); i++)
{
int j = ve[x][i];
if (j == fa) continue;
dep[j] = dep[x]+1;
dfs1(j, x);
cnt[x] += cnt[j];
}
}
void dfs2(int x, int fa)
{
for (int i=0; i<ve[x].size(); i++)
{
int j = ve[x][i];
if (j == fa) continue;
f[j] = f[x]-cnt[j]+(n-cnt[j]);
dfs2(j, x);
}
}
int main()
{
cin>>n;
for (int i=1; i<n; i++)
{
int x, y;
cin>>x>>y;
ve[x].push_back(y);
ve[y].push_back(x);
}
dfs1(1, 0);
for (int i=1; i<=n; i++)
{
f[1]+=dep[i];
}
dfs2(1, 0);
ll minn = f[1];
for (int i=1; i<=n; i++)
{
minn = min(minn, f[i]);
}
cout<<minn<<endl;
return 0;
}