【题目链接】
【题目描述】
设有一棵二叉树(如下图),其中圈中的数字表示结点中居民的人口,圈边上数字表示结点编号。现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻结点之间的距离为11。就本图而言,若医院建在11处,则距离和=4+12+2×20+2×40=136=4+12+2×20+2×40=136;若医院建在33处,则距离和=4×2+13+20+40=81=4×2+13+20+40=81……
【输入】
第一行一个整数nn,表示树的结点数(n≤100n≤100)。接下来的nn行每行描述了一个结点的状况,包含三个整数,整数之间用空格(一个或多个)分隔,其中:第一个数为居民人口数;第二个数为左链接,为00表示无链接;第三个数为右链接,为00表示无链接。
【输出】
一个整数,表示最小距离和。
【输入样例】
5
13 2 3
4 0 0
12 4 5
20 0 0
40 0 0
【输出样例】
81
【题解】
深搜
#include <iostream>
#include <cstring>
#include <climits>
using namespace std;
int sum,vis[105],ans =INT_MAX;
struct node{
int val;
int left,right,parent;
};
node node[105];
void dfs(int step,int pos){
sum+=step*node[pos].val;//计算路径
if(node[pos].parent && !vis[node[pos].parent]){//有父节点 并且父节点并没有被访问
vis[node[pos].parent]=1;//注意点:访问后要设置值为1
dfs(step+1,node[pos].parent);
}
if(node[pos].left && !vis[node[pos].left]){
vis[node[pos].left]=1;
dfs(step+1,node[pos].left);//注意点:访问后要设置值为1
}
if(node[pos].right && !vis[node[pos].right]){
vis[node[pos].right]=1;
dfs(step+1,node[pos].right);//注意点:访问后要设置值为1
}
}
int main(){
int n,i;
cin>>n;
for(i=1;i<=n;i++){
cin>>node[i].val>>node[i].left>>node[i].right;
node[node[i].left].parent = i;//此处记录的结点位置 不是结点的值
node[node[i].right].parent = i;
}
for(i=1;i<=n;i++){
sum=0;
memset(vis,0,sizeof(vis));//将vis数组进行初始化为0
vis[i]=1;//记录下已经访问位置
dfs(0,i);
ans=min(sum,ans);
}
cout<<ans;
}
广搜
#include <bits/stdc++.h>
using namespace std;
struct node{
int val,step;//因为广搜我们要借助队列来进行递推操作 要记录步长
int left,right,parent;
}t[105];
int sum,ans = INT_MAX,vis[105];
void bfs(int pos){
vis[pos] = 1;
queue<node> nodes;
node tt = t[pos];
tt.step = 0;//设置步长
nodes.push(tt);
while(!nodes.empty()){
node front = nodes.front();
sum+= front.val*front.step;
nodes.pop();
//----------------------------错误演示-----------------------------
// if(t[pos].parent && !vis[t[pos].parent]){//应判断头节点的父节点
// vis[t[pos].parent] = 1;//标记父节点已被访问
// node tt2 = t[t[pos].parent];
// tt2.step = tt.step+1;//头节点步长+1
// nodes.push(tt2);
// }
// if(t[pos].left && !vis[t[pos].left]){
// vis[t[pos].left] = 1;
// node tt2 = t[t[pos].left];
// tt2.step = tt.step+1;
// nodes.push(tt2);
// }
// if(t[pos].right && !vis[t[pos].right]){
// vis[t[pos].right] = 1;//访问父节点
// node tt2 = t[t[pos].right];
// tt2.step = tt.step+1;
// nodes.push(tt2);
// }
if(front.parent && !vis[front.parent]){//当前结点不为空 并且结点并没有被访问过
vis[front.parent] = 1;//标记父节点已被访问
node tt2 = t[front.parent];//对父节点进行数据拷贝
tt2.step = front.step+1;//头节点的步长+1
nodes.push(tt2);
}
if(front.left && !vis[front.left]){//当前结点不为空 并且结点并没有被访问过
vis[front.left] = 1;
node tt2 = t[front.left];
tt2.step = front.step+1;
nodes.push(tt2);
}
if(front.right && !vis[front.right]){//当前结点不为空 并且结点并没有被访问过
vis[front.right] = 1;//访问父节点
node tt2 = t[front.right];
tt2.step = front.step+1;
nodes.push(tt2);
}
}
}
int main(){
int n,i;
cin>>n;
for(i=1;i<=n;i++){
cin>>t[i].val>>t[i].left>>t[i].right;
t[t[i].left].parent = i;
t[t[i].right].parent = i;
}
for(i=1;i<=n;i++){
sum=0;
memset(vis,0,sizeof(vis));
vis[i]=1;
bfs(i);
ans=min(ans,sum);
}
cout<<ans;
}