洛谷 P1364 医院设置 (BFS,动态规划)

题目描述

设有一棵二叉树,如图:

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

输入格式

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

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

输出格式

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

输入输出样例

输入 #1

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

 输出 #1

81

 输入 #2

9
21 2 3
91 4 5
12 0 0
9 6 0
5 7 0
97 0 0
76 8 0
7 9 0
99 0 0

 输出 #2

822

AC代码

#include<iostream>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<cstring>
using namespace std;
queue<int>Q;
int dp[105][105]={1000000};//存储各个节点之间的距离 
bool vis[105][105];//存储两个点之间是否相连 
int mp[105];//在BFS中存储x点到各个节点的距离 
int num[105];//输入后存储各个节点的权值 
int ans[105][105];//存储各个节点之间的距离 
struct node{
	int father;
	int Lchild;
	int Rchild;
}tree[200];//用结构体存储节点的父节点和两个子节点 

//用BFS找出一个点到各个点的距离 
void BFS(int x){
	memset(mp,-1,sizeof(mp));//初始化 
	int start,next;
	start=x;
	mp[x]=0;
	Q.push(start);
	while(!Q.empty()){
		start=Q.front();
		Q.pop();
		//三个方向走,父节点,左节点,右节点 
		next=tree[start].father;
		if(vis[start][next]&&next>0&&mp[next]==-1){
			mp[next]=mp[start]+1;
			Q.push(next);
		}
		next=tree[start].Lchild;
		if(vis[start][next]&&next>00&&mp[next]==-1){
			mp[next]=mp[start]+1;
			Q.push(next);
		}
		next=tree[start].Rchild;
		if(vis[start][next]&&next>00&&mp[next]==-1){
			mp[next]=mp[start]+1;
			Q.push(next);
		}
	}
}
int main(){
	//初始化 
	for(int i=1;i<=100;i++)
        for(int j=1;j<=100;j++)
            if(i==j)
                dp[i][j]=0;
            else
                dp[i][j]=9999999;
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		int w,u,v;
		cin>>w>>u>>v;
		dp[i][i]=0;num[i]=w;
		vis[i][u]=true;vis[i][v]=true;
		vis[u][i]=true;vis[v][i]=true;
		tree[u].father=i;tree[v].father=i;
		tree[i].Lchild=u;tree[i].Rchild=v;
		dp[i][tree[i].father]=w;
		if(u!=0){
			dp[i][u]=w;
		}
		if(v!=0){
			dp[i][v]=w;
		}
	}
	
	for(int i=1;i<=n;i++){
		BFS(i);
		for(int j=1;j<=n;j++){
			ans[i][j]=mp[j];
		}
	}
	int Min=99999999;//存储最小距离 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			dp[i][j]=ans[i][j]*num[i];
		}
	}
	for(int i=1;i<=n;i++){
		int sum=0;
		for(int j=1;j<=n;j++){
			sum+=dp[j][i];
		}
		if(Min>=sum) Min=sum;
	}
	cout<<Min<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瘾ิۣۖิۣۖิۣۖิꦿ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值