题目:
分析:这个题,我咋记得做过呢?
自己当时还差不多想出来了很好的思路了。
而且那个题是树的结点是有权值的,这个没有。
在做题的时候发现,最近给的题啊,都没有给出根。自己之前都没有注意过,树的根不是任意取的,与其相连的边应该不能有3个。等等,人家又没有说是2叉树,傻了傻了。根还是随便取的。
而且不需要强制的建树,只要标明father,就可以了(至少在这个题中是这样)。。。。。(列为精华也是这个原因,提醒自己要多分析,多思考。)
而且要注意的是统计的是儿子个数,差点搞错成儿子到达其的个数。
代码:这次写着怎么这么费劲,写了2h,哎:
1.统计的是自身(也可以不包含自身)以及自身子孙的数量。
2.需要先求出根的结果,一个深搜,dp。很好。//这个dp也是很好的。
3.最终核心的dp。
4.而且自己有改进,不需要一直fa,就是把父的哪个值改为-1了。
#include<bits/stdc++.h>
using namespace std;
int m;
vector<vector<int> > vv;
int son[50005];//儿子及其儿子后代的个数,不包含自己
int ans[50005];
int f_son(int fa,int now)
{//计算son【now】
for(int i=0;i<vv[now].size();i++)
{
if(vv[now][i]==fa)
{
vv[now][i]=-1;
continue;
}
son[now]=son[now]+1+f_son(now,vv[now][i]);
}
return son[now];
}
int f_1(int now)
{//子及后代到达now的值。
int c=0;
if(vv[now].size()==1&&vv[now][0]==-1) return 0;//到达叶子节点
for(int i=0;i<vv[now].size();i++)
{
if(vv[now][i]==-1) continue;
c=c+f_1(vv[now][i]);
}
return c+son[now];
}
void f(int now,int s)
{
ans[s]=ans[now]-(son[s]+1)+m-(son[s]+1);
for(int i=0;i<vv[s].size();i++)
{
if(vv[s][i]==-1) continue;
f(s,vv[s][i]);
}
}
int main()
{
cin>>m;
vector<int> v;
for(int i=0;i<=m;i++)
{
vv.push_back(v);
}
for(int i=1;i<m;i++)
{
int a,b; cin>>a>>b;
vv[a].push_back(b);
vv[b].push_back(a);
}
f_son(-1,1);
//for(int i=1;i<=m;i++) cout<<son[i]<<endl;
ans[1]=f_1(1);
//cout<<ans[1];
for(int i=0;i<vv[1].size();i++)
{
if(vv[1][i]==-1) continue;
f(1,vv[1][i]);
}
int minn=1<<30,loca=-1;
for(int i=1;i<=m;i++)
{
if(minn>ans[i])
{
loca=i;
minn=ans[i];
}
}
cout<<loca<<' '<<minn;
}