医院设置

【问题描述】

       设有一棵二叉树,如图5-1:

                                                                                                    131

                                                                          /   \

                                                                        24  123

                                                                                /  \

                                                                           420 405

    其中,圈中的数字表示结点中居民的人口。圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为l。如上图中,若医院建在:

【输入】

    第一行一个整数n,表示树的结点数。(n≤100)

    接下来的n行每行描述了一个结点的状况,包含三个整数,整数之间用空格(一个或多个)分隔,其中:第一个数为居民人口数;第二个数为左链接,为0表示无链接;第三个数为右链接。

【输出】

       一个整数,表示最小距离和。

【样例】

       hospital.in                          hospital.out

       5                                        81

       13 2 3

       4 0 0

       12 4 5

       20 0 0

       40 0 0

【知识准备】

       图的遍历和最短路径。

【算法分析】

       本题的求解任务十分明了:求一个最小路径之和。

       根据题意,对n个结点,共有n个路径之和:用记号Si表示通向结点i的路径之和,则,其中Wj为结点j的居民数,g(i,j)为结点j到结点i的最短路径长度。下面表中反映的是样例的各项数据:

j

g(i,j)

i

1

2

3

4

5

Si

1

0

1

1

2

2

0×13+1×4+1×12+2×20+2×40=136

2

1

0

2

3

3

1×13+0×4+2×12+3×20+3×40=217

3

1

2

0

1

1

1×13+2×4+0×12+1×20+1×40=81

4

2

3

1

0

2

2×13+3×4+1×12+0×20+2×40=130

5

2

3

1

2

0

2×13+3×4+1×12+2×20+0×40=90

 

       从表中可知S3=81最小,医院应建在3号居民点,使得所有居民走的路径之和为最小。

       由此可知,本题的关键是求g[i,j],即图中任意两点间的最短路径长度。

       求任意两点间的最短路径采用下面的弗洛伊德(Floyd)算法。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define M 110
#define INF 999999
using namespace std;
int f[M][M],a[M],dis[M],n;
int main()
{
    freopen("jh.in","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
        f[i][j]=INF;
    for(int i=1;i<=n;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        a[i]=x;
        f[i][y]=f[y][i]=1;
        f[i][z]=f[z][i]=1;
    }
    for(int k=1;k<=n;k++)
      for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
          if(i!=j&&j!=k&&i!=k)
            f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
        if(i!=j)
          dis[i]+=f[i][j]*a[j];
    sort(dis+1,dis+n+1);
    printf("%d",dis[1]);
    return 0;
}
View Code

 

posted @ 2016-06-18 20:24  karles~  阅读(665)  评论(0编辑  收藏  举报