【7011】医院设置
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\n",min_n);
}
int main()
{
//freopen("F:\\rush.txt","r",stdin);
input_data();
get_ans();
output_ans();
return 0;
}

浙公网安备 33010602011771号