洛谷:P1395 会议(树,重心)

题目:

在这里插入图片描述

分析:这个题,我咋记得做过呢?

自己当时还差不多想出来了很好的思路了。

而且那个题是树的结点是有权值的,这个没有。

在做题的时候发现,最近给的题啊,都没有给出根。自己之前都没有注意过,树的根不是任意取的,与其相连的边应该不能有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;
}

猜你喜欢

转载自blog.csdn.net/weixin_42721412/article/details/107906850