洛谷题单指南-二叉树-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;
}

 

posted @ 2024-03-15 14:55  五月江城  阅读(67)  评论(0编辑  收藏  举报