#include using namespace std; const int N = 210; bool st[N]; //是不是走过了 int n, ans = 0x3f3f3f3f; struct Node { int sq_sum; //几号结点 int left; //左儿子 int right; //右儿子 int value; //此结点的人数 int parent; //父亲是哪结点 } nodes[N]; /** * 功能:计算以u为起点,step步数下的权值 * @param u * @param step * @return */ int dfs(int u, int step) { //不加st数组的话,会Memory Limit Exceed 超出内存限制 //如果不加st数组的话,就会发生:它调了它的父亲,它的父亲又调了它,来来回回,不死不休~,这样看来,状态数组是多么的重要啊~ //问题1:什么时间退出递归?nodes[u].num==0表示找到了一个终端结点,就是叶子 if (nodes[u].num == 0 || st[u] == true) return 0; //标识为已使用过 st[u] = true; //问题2:如何计算整体的权值 //这里就是个深度优先搜索,三个侦察兵,左子树,右子树,父子树的距离和. //分别对三个方向的侦查兵说:以你为根的子树,距离我step+1这么远,你负责统计一下你子树的距离和! //[u,step]的权值=dfs(左儿子)+dfs(右儿子)+自己的权值+dfs(父亲) return dfs(nodes[u].left, step + 1) + dfs(nodes[u].right, step + 1) + dfs(nodes[u].parent, step + 1) + nodes[u].value * step; } int main() { //读入数据 cin >> n; for (int i = 1; i <= n; i++) { //读入权值,左儿子,右儿子 cin >> nodes[i].value >> nodes[i].left >> nodes[i].right; //记录结点号 nodes[i].num = i; //记录左右儿子的父亲节点 nodes[nodes[i].left].parent = i; //为了找到父亲 nodes[nodes[i].right].parent = i;//为了找到父亲 } //遍历每个结点作为医院部署地 for (int i = 1; i <= n; i++) { //每次出发前,注意要清空状态数组,防止状态记录错误 memset(st, 0, sizeof st); //每个结点作为医院部署地,都会产生一个距离和,取最小值 ans = min(ans, dfs(i, 0)); } cout << ans << endl; return 0; }