洛谷题单指南-二叉树-P1364 医院设置
原题链接:https://www.luogu.com.cn/problem/P1364
题意解读:医院的位置使所有居民所走的路程之和为最小,即找到一个节点,该节点到其他所有节点的距离*其他节点的权值即人数之和最小。
解题思路:
看起来是一个二叉树问题,本质上是一个图论问题,有三种方式可以求解:
1、计算每两个节点之间的最短路径(Floyd算法),然后枚举在每一个点建医院,计算所有居民的路程之和,求最小值。
2、从每一个节点出发,进行BFS搜索,搜索过程中计算每个点到起始点的路程*人数,求和,对和取最小值。
3、方法同2,只不过采用DFS搜索。
既然在二叉树板块,就采用二叉树的方式处理
要实现从每一个节点出发进行BFS或者DFS,需要存储每个节点的子节点、父节点信息
struct node
{
int weight; //人口数
int sub[3]; //sub[0]父节点、sub[1]左子节点、sub[2]右子节点
} tree[N];
下面给出DFS版本的代码,因为个人感觉DFS代码更简洁(但BFS代码没有递归更容易理解)。
100分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
struct node
{
int weight; //人口数
int sub[3]; //sub[0]父节点、sub[1]左子节点、sub[2]右子节点
} tree[N];
bool flag[N];
int n, w, u, v;
int sum, ans = INT_MAX;
//idx是节点号,当前节点距离起始节点路径长度depth,路程和sum
void dfs(int idx, int depth)
{
flag[idx] = true;
if(depth > 0) sum += tree[idx].weight * depth;
for(int i = 0; i < 3; i++)
{
if(!flag[tree[idx].sub[i]]) dfs(tree[idx].sub[i], depth + 1);
}
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> w >> u >> v;
tree[i].weight = w;
tree[i].sub[1] = u;
tree[i].sub[2] = v;
if(u) tree[u].sub[0] = i; //记录u的父节点为i
if(v) tree[v].sub[0] = i; //几率v的父节点为i
}
for(int i = 1; i <= n; i++)
{
sum = 0; //路程之和初始化
memset(flag, 0, sizeof(flag)); //flag初始化为false
dfs(i, 0);
ans = min(ans, sum);
}
cout << ans;
return 0;
}