Description
设有一棵二叉树(如右图)。其中,圈中的数字表示结点中居民的人口。圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为1。如 右图中,若医院建在:
1处,则距离和=4+12+220+240=136
3处,则距离和=4*2+13+20+40=81
………….
Input
第一行一个整数n,表示树的结点数。(n<=100)
接下来的n行每行描述了一个结点的状况,包含三个整数,整数之间用空格(一个或多个)分隔,其中:第一个数为居民人口数;第二个数为左链接,为0表示无链接;第三个数为右链接。
Output
一个整数,表示最小距离和。
Sample Input
5
13 2 3
4 0 0
12 4 5
20 0 0
40 0 0
Sample Output
81
解题思路
先枚举起点,求出最短路后用 最短路 x 人数,比较出最小的
SPFA的处理会麻烦:
- 输入边的时候,因为是无向图,所以一共要存4条边
- 如果是0,必须排除,不然会连到0,就中断了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct DT{
int to,next;
}a[30000];
int dis[10000],head[10000],n,num,lt[10000];
int h,t,v[10000],f[10000];
long long Gun=0x7fffffff;
void SPFA(int s){
memset(f,0,sizeof(f));
h=0,t=1,v[1]=s,dis[s]=0,f[s]=1;
while(h++<t){
for(int i=head[v[h]];i;i=a[i].next){
if(dis[v[h]]+1<dis[a[i].to]){
dis[a[i].to]=dis[v[h]]+1;
if(!f[a[i].to]){
v[++t]=a[i].to;
f[a[i].to]=1;
}
}
}
f[v[h]]=0;
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int x,y,s;
scanf("%d%d%d",<[i],&x,&y);
if(y>0){//右链接
a[++num].to=y,a[num].next=head[i],head[i]=num;
a[++num].to=i,a[num].next=head[y],head[y]=num;
}
if(x>0){//左连接
a[++num].to=x,a[num].next=head[i],head[i]=num;
a[++num].to=i,a[num].next=head[x],head[x]=num;
}
}
for(int g=1;g<=n;g++){//枚举起点
memset(dis,0x7f,sizeof(dis));
SPFA(g);
long long b=0;
for(int i=1;i<=n;i++)
b+=lt[i]*dis[i]; //人数 x 最短路
Gun=min(Gun,b);
}
printf("%lld",Gun);
}