# 医院设置

## 输入输出样例

### 输入样例 #1

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


### 输出样例 #1

81


# 分析

void dfs(int u, int father, int depth) {
siz[u] = w[u];
for (int i = head[u]; i; i = edge[i].nxt)
if (edge[i].v != father) {
dfs(edge[i].v, u, depth + 1);
siz[u] += siz[edge[i].v];
}
dp[1] += w[u] * depth;
}


• w代表此点权值，也就是题目中的w
• siz代表此点大小
• dp代表以此点为根的总距离

$dp_v = dp_u - siz_v + siz_1 - siz_v$

dp环节伪代码：

void work(int u, int father) {
for (int i = head[u]; i; i = edge[i].nxt)
if (edge[i].v != father) {
dp[edge[i].v] = dp[u] - siz[edge[i].v] * 2 + siz[1];
work(edge[i].v, u);
}
ans = ans < dp[u] ? ans : dp[u];
}


dbxxx，你不是说此处不上代码，别人也能写出来吗？那你为啥还上？

# 代码

/*
* @Author: crab-in-the-northeast
* @Date: 2020-08-01 22:01:07
*/
//找树的重心，学习于P1364第一篇题解。
#include <iostream>
#include <cstdio>
#include <climits>

const int maxn = 105;

struct Edge {
int v, nxt;
}edge[maxn << 1];

int w[maxn];
int ans = INT_MAX >> 2, dp[maxn];

inline void addEdge(int u, int v) {
edge[++idx].v = v;
}

void dfs(int u, int father, int depth) {
siz[u] = w[u];
for (int i = head[u]; i; i = edge[i].nxt)
if (edge[i].v != father) {
dfs(edge[i].v, u, depth + 1);
siz[u] += siz[edge[i].v];
}
dp[1] += w[u] * depth;
}

void work(int u, int father) {
for (int i = head[u]; i; i = edge[i].nxt)
if (edge[i].v != father) {
dp[edge[i].v] = dp[u] - siz[edge[i].v] * 2 + siz[1];
work(edge[i].v, u);
}
ans = ans < dp[u] ? ans : dp[u];
}

int main(){
std :: scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
std :: scanf("%d", &w[i]);
int a, b;
std :: scanf("%d%d", &a, &b);
if (a) {
}
if (b) {
}
}
dfs(1, 0, 0);
work(1, 0);
printf("%d", ans);
return 0;
}


# 评测记录

posted @ 2020-08-02 17:03  东北小蟹蟹  阅读(83)  评论(0编辑  收藏  举报