P1364 医院设置

题目描述

设有一棵二叉树,如图:

其中,圈中的数字表示结点中居民的人口。圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为 11。如上图中,若医院建在1 处,则距离和 =4+12+2×20+2×40=136=4+12+2×20+2×40=136;若医院建在 33 处,则距离和 =4×2+13+20+40=81=4×2+13+20+40=81。

输入格式

第一行一个整数 �n,表示树的结点数。

接下来的 �n 行每行描述了一个结点的状况,包含三个整数 �,�,�w,u,v,其中 �w 为居民人口数,�u 为左链接(为 00 表示无链接),�v 为右链接(为 00 表示无链接)。

输出格式

一个整数,表示最小距离和。

输入输出样例

输入 #1复制

5						
13 2 3
4 0 0
12 4 5
20 0 0
40 0 0

输出 #1复制

81

说明/提示

数据规模与约定

对于 100%100% 的数据,保证 1≤�≤1001≤n≤100,0≤�,�≤�0≤u,v≤n,1≤�≤1051≤w≤105。

1.这道题我采用的算法是dfs。

2.该题的大概题意为:在一棵二叉树中找出一个点使得其他的点到这个点的路程(节点间距离*元素值)之和最小,输出最小距离。

3. 首先,建树,定义一个结构体,包含四个值,一个存储节点的值,一个存储左孩子,一个存储右孩子,一个存储该节点的父节点。输入时,输入每个节点的值还有左右孩子的值,左右孩子的父节点为当前节点的编号。

4.循环遍历每一个节点,调用dfs函数对每一个进行向上,向左,向右搜索,每一步的搜索都用sum累加当前节点的步数*元素值的值。用一个vis数组来进行记忆化。在主函数中判断输出最小的值即可。

#include"stdio.h"
struct node
{
	int father,left,right,value;
}t[105];
int sum=999999,ans=999999,vis[105];
int min(int a,int b)
{
	if(a>b) return b;
	else return a;
}
void dfs(int step,int pos)
{
	int i,f,l,r;
	sum+=step*t[pos].value;
	f=t[pos].father;l=t[pos].left;r=t[pos].right;
	if(f&&!vis[f])
	{
		vis[f]=1;
		dfs(step+1,f);
	}
	if(l&&!vis[l])
	{
		vis[l]=1;
		dfs(step+1,l);
	}
	if(r&&!vis[r])
	{
		vis[r]=1;
		dfs(step+1,r);
	}
}
main()
{
	int n,i,j;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%d %d %d",&t[i].value,&t[i].left,&t[i].right);
		t[t[i].left].father=t[t[i].right].father=i;
	}
	for(i=1;i<=n;i++)
	{
		sum=0;
		for(j=0;j<=105;j++)
		vis[j]=0;
		vis[i]=1;
	    dfs(0,i);
		ans=min(sum,ans);
		//printf("%d\n",ans);
	}	
	printf("%d",ans);
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值