Time Limit: 1 second
Memory Limit: 64 MB
【问题描述】
设有一棵二叉树,如图1:
其中,圈中的数字表示结点中居民的人口。圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻结点之间的距离为1。如图1所示,若医院建在:
1处,则距离和=4+12+2*20+2*40=136
3处,则距离和=4*2+13+20+40=81
【输入格式】
第1行一个整数n,表示树的结点数。(n≤100)
接下来的n行每行描述了一个结点的状况,包含三个整数,整数之间用空格(一个或多个)分隔,其中:第一个数为居民人口数;第二个数为左链接,为0表示无链接;第三个数为右链接。
【输出格式】
一个整数,表示最小距离和。
【输入样例1】
5 13 2 3 4 0 0 12 4 5 20 0 0 40 0 0
【输出样例1】
81
【题解】
首先,在输入二叉树的时候,记录下父亲结点和子结点的连通情况。若两点连通,则置bo[i][j]为1。然后用floyed算法算出任意两个结点之间的距离(按照求最短路的办法来求就可以了)。
然后进行枚举,枚举医院设置在第i个结点的情况。for一遍其他位置,用一个sum来进行累加,sum+=a[j]*bo[i][j]。然后尝试更新最小距离。
最后输出就可以了。
【代码】
#include <cstdio> #include <cstring> int n,a[120],bo[120][120],min_n = 2100000000; void input_data() { memset(bo,0,sizeof(bo)); scanf("%d",&n); for (int i = 1;i <= n;i++) { int l,r; scanf("%d%d%d",&a[i],&l,&r); if (l!=0) bo[i][l] =1,bo[l][i] = 1; //这个连通情况是双向的。 if (r!=0) bo[i][r] = 1,bo[r][i] = 1; } } void get_ans() { for (int k = 1;k <= n;k++) //利用floyed算法算出任意两点之间的距离;(要按照求最短路的方法求) for (int i = 1;i <= n;i++) for (int j = 1;j <= n;j++) if ((bo[i][k] >0) && (bo[k][j] >0)) { if (bo[i][j] == 0) bo[i][j] = bo[i][k] + bo[k][j]; else if (bo[i][j] > bo[i][k]+bo[k][j]) bo[i][j] = bo[i][k]+bo[k][j]; } for (int i = 1;i <= n;i++) //枚举医院设置在第i个结点。 { int sum = 0; for (int j = 1;j <= n;j++) if (j != i) sum += bo[i][j]*a[j]; //bo[i][j]即表示其他结点到i结点的距离 if (sum < min_n) //尝试更新累加的最小值。 min_n = sum; } } void output_ans() { printf("%d ",min_n); } int main() { //freopen("F:\rush.txt","r",stdin); input_data(); get_ans(); output_ans(); return 0; }