洛谷P1395 会议(图论,树形DP)

洛谷P1395 会议(图论,树形DP)

题目描述
有一个村庄居住着n个村民,有n-1条路径使得这n个村民的家联通,每条路径的长度都为1。现在村长希望在某个村民家中召开一场会议,村长希望所有村民到会议地点的距离之和最小,那么村长应该要把会议地点设置在哪个村民的家中,并且这个距离总和最小是多少?若有多个节点都满足条件,则选择节点编号最小的那个点。

输入格式
第一行。一个数n,表示有n个村民。

接下来n-1行,每行两个数字a和b,表示村民a的家和村民b的家之间存在一条路径。

输出格式
一行输出两个数字x和y

x表示村长将会在哪个村民家中举办会议

y表示距离之和的最小值

输入

4
1 2 
2 3 
3 4 

输出

2 4

具体代码(注:缝的洛谷大佬Y_B_Y代码,感兴趣的兄弟可以去该题题解区找了看)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>

#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long

using namespace std;

const int N = 5e4+5;

struct edge
{
	int t, nex;
}e[N<<1];

int n, head[N], d[N], ct[N], fa[N];
//d[]储存距离之和  ct[]储存子树的结点数  fa:father

int tot, ans, minn = 1e9+7;

void add(int x,int y)//add edge
{
	e[++tot].t = y;
	
	e[tot].nex = head[x];
	
	head[x] = tot;
}

void dfs(int x,int st)
{
	for(int i=head[x];i!=0;i=e[i].nex)//visit all edges that from x
	{
		if(e[i].t!=fa[x])//该边没有指向父结点  
		{
			++ct[x];// 以x为根的子树,树的总结点数加一 
			
			fa[e[i].t] = x;//确认x孩子结点的父结点为x
			
			dfs(e[i].t,st+1);//遍历子树 
			
			ct[x] += ct[e[i].t];//用x的子树的子树去修改值 
		}
	}
	
	d[1] += st;//记录所有点到1的距离之和  
}

void fd(int x)//进行树状DP! 
{
	for(int i=head[x];i!=0;i=e[i].nex)
	{
		if(e[i].t!=fa[x])
		{//关键:d[child] = d[father] - (child's nodes) + (other nodes)
			d[e[i].t] = d[x] - ct[e[i].t] - 1 + (n - ct[e[i].t] - 1);
		//意思:所有child的子树结点与child的距离减少1,其余结点增加1	
			fd(e[i].t);//递归处理剩下的点
		}
	}
	
	return;
}

int main()
{
	scanf("%d",&n);
	
	for(int i=1;i<n;++i)
	{
		int a, b;
		
		scanf("%d %d",&a,&b);
		
		add(a,b);
		
		add(b,a);
	}
	
	dfs(1,0);//默认以1为该树的根
	
	fd(1);//从根1开始,推得各点的D值
	
	for(int i=1;i<=n;++i)
	{
		if(d[i]<minn)//遍历所有节点,寻找到距离之和最小的点
		{
			minn = d[i];
			
			ans  = i;
		}
	}
	
	printf("%d %d\n",ans,minn);
	
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值