题目描述
设有一棵二叉树,其中圈中的数字表示结点居民的人口,圈边上的数字表示结点的编号。现在要求在某个结点上建立一个医院,使所有居民所走的路径之和为最小,同时约定,相邻接点之间的距离为1,就本图而言,若医院建在1处,则距离和=4+12+2*20+2*40=136,若医院建在3处,则距离和=4*2+13+20+40=81,…
输入格式
其中第一行一个整数n,表示树的结点数(n<=100)。接下来的N行每行描述了一个结点的状况,包括三个整数,整数之间用空格(一个或多个)分隔,其中:第一个数为居民人口数;第二个数为左链接,为0表示无链接;第三个数为右链接。
输出格式
只有一个整数,表示最小距离和。
又开始回来做水题了。。悲哀的人生。。
一个树上的中位数就完了。先一个dfs与处理出每一个子树的节点总数,和初始状态的ans值。然后又是一个dfs移动到最优解。总时间复杂度O(n)
#include <string>
#include <cstdio>
long ans = 0;
long h[102];
long l[102];
long r[102];
long sum[102];
long total;
long flood(long i,long s)
{
ans += h[i]*s;
long rs = 0;
if (l[i])
rs += flood(l[i],s+1);
if (r[i])
rs += flood(r[i],s+1);
sum[i] = rs+h[i];
return sum[i];
}
void dfs(long i)
{
if (l[i] && sum[l[i]]>(total-sum[l[i]]))
{
ans += total-sum[l[i]]-sum[l[i]];
dfs(l[i]);
}
if (r[i] && sum[r[i]]>(total-sum[r[i]]))
{
ans += total-sum[r[i]]-sum[r[i]];
dfs(r[i]);
}
}
long getint()
{
char tmp;long rs=0;bool sgn=1;
do tmp=getchar();
while (!isdigit(tmp)&&tmp-'-');
if (tmp=='-'){tmp=getchar();sgn=0;}
do rs=(rs<<3)+(rs<<1)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
int main()
{
freopen("hospital.in","r",stdin);
freopen("hospital.out","w",stdout);
long n = getint();
for (long i=1;i<n+1;i++)
{
h[i] = getint();
l[i] = getint();
r[i] = getint();
}
flood(1,0);
total = sum[1];
dfs(1);
printf("%ld",ans);
return 0;
}