Floyd算法应用-医院选址问题

1)问题描述

n个村庄之间的交通图可以用有向网图来表示,图中边<vi, vj>上的权值表示从村庄i到村庄j的道路长度。现在要从这n个村庄中选择一个村庄新建一所医院,问这所医院应建在哪个村庄,才能使所有的村庄离医院都比较近?

2) 基本要求

(1) 建立模型,设计存储结构;

(2) 设计算法完成问题求解;

(3) 分析算法的时间复杂度。

3) 设计思想

医院选址问题实际是求有向图中心点的问题。首先定义顶点的偏心度。

设图G=(VE),对任一顶点k,称E(k)=max{d(i, k)}(iV)为顶点k的偏心度。显然,偏心度最小的顶点即为图G的中心点。

如图3(a)所示是一个带权有向图,其各顶点的偏心度如图(b)所示。

4)医院选址问题的算法用伪代码描述如下:

1.对加权有向图,调用Floyd算法,求每对顶点间最短路径长度的矩阵;

2.对最短路径长度矩阵的每列求大值,即得到各顶点的偏心度;

3.具有最小偏心度的顶点即为所求。

5)代码附录

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4 #define INFINITY 1000000
  5 #define MAX_VERTEX_NUM 20
  6
  7 //定义弧的权值信息
  8 typedef struct Arccell
  9 {
 10     int adj; //权值
 11 } Arccell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //图的邻接矩阵
 12 //定义结点信息
 13 typedef struct VertexInfo
 14 {
 15     char name[20];//结点[村庄]名称
 16     int position;//定点编号
 17 } VertexInfo;
 18 //图的结构
 19 typedef struct Mgraph
 20 {
 21     VertexInfo vexs[MAX_VERTEX_NUM];//顶点数组
 22     AdjMatrix arcs;//邻接矩阵
 23     int vernum,arcnum;//分别指定顶点数和边数
 24 } Mgraph;
 25
 26
 27 //对图的初始化
 28 Mgraph initgraph()
 29 {
 30     Mgraph c;
 31     printf("请输入该图的顶点个数和弧的个数:\n");
 32     printf("顶点个数:");
 33     scanf("%d",&c.vernum);
 34     printf("弧的个数:");
 35     scanf("%d",&c.arcnum);
 36     //依次设置顶点编号
 37     for(int i=0; i<c.vernum; i++)
 38     {
 39         c.vexs[i].position=i;
 40     }
 41     //依次输入各顶点信息
 42     /*
 43     strcpy(c.vexs[0].name,"a");
 44     strcpy(c.vexs[1].name,"b");
 45     strcpy(c.vexs[2].name,"c");
 46     strcpy(c.vexs[3].name,"d");
 47     strcpy(c.vexs[4].name,"e");
 48
 49     */
 50     printf("\n请依次输入各个村庄的名称:\n");
 51     for(int i=0;i<c.vernum;i++)
 52     {
 53         printf("村庄%d:",i);
 54         scanf("%s",&c.vexs[i].name);
 55
 56     }
 57
 58     //依次设置各弧的信息
 59     for(int i=0; i<c.vernum; i++)
 60     {
 61         //先初始化邻接矩阵,相同点设置为0,其他全部设置为INFINITY(无穷大)
 62         for(int j=0; j<c.vernum; j++)
 63         {
 64             c.arcs[i][j].adj=INFINITY;
 65             if(i==j)
 66             {
 67                 c.arcs[i][j].adj=0;
 68             }
 69         }
 70     }
 71     //再依次输入需要设置的权值
 72     int i,j,k;
 73     printf("请输入需要设置的弧长及其两端顶点[输入3个0结束]:\n");
 74     while(scanf("%d%d%d",&i,&j,&k))
 75     {
 76         if(i==0&&j==0&k==0)
 77             break;
 78         c.arcs[i][j].adj=k;
 79     }
 80     /*
 81     c.arcs[0][1].adj=1;
 82     c.arcs[1][2].adj=2;
 83     c.arcs[2][3].adj=2;
 84     c.arcs[2][4].adj=4;
 85     c.arcs[3][1].adj=1;
 86     c.arcs[3][2].adj=3;
 87     c.arcs[4][3].adj=5;
 88     */
 89     return c;
 90 }
 91
 92 //输出邻接矩阵
 93 void printMatrix(Mgraph c)
 94 {
 95     printf("该图的邻接矩阵如下所示:\n");
 96     int count=0;//用于计数
 97     for(int i=0; i<c.vernum; i++)
 98         for(int j=0; j<c.vernum; j++)
 99         {
100             if(c.arcs[i][j].adj==INFINITY)
101                 printf("   #");
102             else
103                 printf("%4d",c.arcs[i][j].adj);
104             count++;
105             if(count%c.vernum==0)
106                 printf("\n");
107         }
108 }
109
110 void ShortestPath_Floyd(Mgraph G,int dis[][MAX_VERTEX_NUM])
111 {
112     //用floyd算法求有向网G中各对定点v和w之间的最短路径及其带权长度dis[v][w]
113     for(int v=0; v<G.vernum; v++)
114         for(int w=0; w<G.vernum; w++)
115         {
116             //对各结点之间初始化已知距离
117             dis[v][w]=G.arcs[v][w].adj;
118         }
119
120     for(int u=0; u<G.vernum; u++)
121         for(int v=0; v<G.vernum; v++)
122             for(int w=0; w<G.vernum; w++)
123             {
124                 if(dis[v][u]+dis[u][w]<dis[v][w])
125                 {
126                     //从v经u到w的路径更短
127                     dis[v][w]=dis[v][u]+dis[u][w];
128                 }
129             }
130
131 }
132 //输出距离矩阵
133 void printDis(Mgraph G,int dis[MAX_VERTEX_NUM][MAX_VERTEX_NUM])
134 {
135     printf("\n经过Flyod算法之后各顶点之间的距离如下:\n");
136     for(int i=0; i<G.vernum; i++)
137     {
138         for(int j=0; j<G.vernum; j++)
139         {
140             if(dis[i][j]>=1000000)
141                 printf("   #");
142             else
143                 printf("%4d",dis[i][j]);
144
145         }
146         printf("\n");
147     }
148 }
149
150 //得到偏心度degree[]数组
151 void getDegree(Mgraph G,int dis[MAX_VERTEX_NUM][MAX_VERTEX_NUM],int degree[])
152 {
153     for(int i=0;i<G.vernum;i++)
154     {
155         int max=dis[0][i];
156         for(int j=0;j<G.vernum;j++)
157         {
158             if(dis[j][i]>max)
159                 max=dis[j][i];
160         }
161         degree[i]=max;
162     }
163 }
164
165
166
167 int main()
168 {
169     printf("**********欢迎使用医院选址系统*********\n");
170     Mgraph c=initgraph();
171     system("cls");
172
173     //输出邻接矩阵
174     getchar();
175     printMatrix(c);
176
177     //定义距离数组,调用Floyd算法得到结果
178     int dis[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
179     ShortestPath_Floyd(c,dis);
180
181     //输出各个顶点之间的距离矩阵
182     getchar();
183     printDis(c,dis);
184
185     //存放偏心度数
186     int degree[c.vernum];
187     getDegree(c,dis,degree);
188
189     //显示各顶点的偏心度
190     getchar();
191     printf("\n各顶点的偏心度如下所示:\n");
192     for(int i=0;i<c.vernum;i++)
193     {
194         if(degree[i]>=1000000)
195             printf("   #\n");
196         else
197             printf("%4d\n",degree[i]);
198     }
199
200     //得到最小村庄的编号和名称
201     int num;
202     int min=degree[0];
203     for(int i=0;i<c.vernum;i++)
204     {
205         if(min>degree[i])
206             min=degree[i];
207     }
208
209     for(int i=0;i<c.vernum;i++)
210     {
211         if(min==degree[i])
212         {
213             num=i;
214             break;
215         }
216     }
217     getchar();
218     printf("\n偏心度最小的村庄编号:%4d\n",num);//输出偏心度最小的村庄编号
219     printf("医院应该建立在村庄:   %4s \n",c.vexs[num].name);
220     return 0;
221
222 }

6)测试结果

1.首先运行程序,出现如图6.1所示。

          图6.1  程序运行开始界面

2.输入顶点个数和边的个数之后,会提示输入村庄名称,如图6.2所示。

图6.2 提示输入村庄名称界面

3.村庄名称输入结束之后,提示输入边的起始点和权值,如图6.3所示。

图6.3 提示输入边相关信息的界面

4.输入边的信息,以输入0 0 0结束,如图6.4所示。

图6.4 输入边相关信息界面

5.边的信息输入完成之后,回车得到邻接矩阵,如图6.5所示。

图6.5 邻接矩阵表

6.继续回车,得到距离矩阵,如图6.6所示。

图6.6 距离矩阵表

7.回车,得到偏心度表,如图6.7所示。

图6.7 各顶点偏心度

8.最后程序输出医院选址结果,如图6.8所示。

图6.8 最终结果

时间: 2024-10-14 09:22:17

Floyd算法应用-医院选址问题的相关文章

医院选址问题【Floyd算法】

1)问题描述 n个村庄之间的交通图可以用有向网图来表示,图中边<vi, vj>上的权值表示从村庄i到村庄j的道路长度.现在要从这n个村庄中选择一个村庄新建一所医院,问这所医院应建在哪个村庄,才能使所有的村庄离医院都比较近? 2) 基本要求 (1) 建立模型,设计存储结构: (2) 设计算法完成问题求解: (3) 分析算法的时间复杂度. 3) 设计思想 医院选址问题实际是求有向图中心点的问题.首先定义顶点的偏心度. 设图G=(V,E),对任一顶点k,称E(k)=max{d(i, k)}(i∈V)

[Swust OJ 412]--医院设置(floyd算法)

题目链接:http://acm.swust.edu.cn/problem/412/ Time limit(ms): 1000 Memory limit(kb): 65535 Description 设有一棵二叉树,如图:  其中,圈中的数字表示结点中居民的人口.圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相信接点之间的距离为1.如上图中,若医院建在: 1处,则距离和=4+12+2*20+2*40=136 3处,则距离和=4*2+13+20+

ACM: POJ 3660 Cow Contest - Floyd算法

链接 Cow Contest Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Description N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we all know, some cows code better than others. Eac

最短路径Dijkstra算法和Floyd算法整理、

转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹

最短路径——Floyd算法

如何求一张图中任意两顶点之间的最短路径长度,这里写一种最简单的算法——Floyd算法: 1 #include<stdio.h> 2 3 #define inf 9999 4 5 int main() 6 { 7 int e[10][10]; //用邻接矩阵表示图 8 printf("请输入顶点和边的数目:"); 9 int n,m; 10 scanf("%d%d",&n,&m); 11 for(int i=0;i<n;i++) 12

HDOJ 1217 Arbitrage(拟最短路,floyd算法)

Arbitrage Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5679    Accepted Submission(s): 2630 Problem Description Arbitrage is the use of discrepancies in currency exchange rates to transform

44. 蛤蟆的数据结构笔记之四十四弗洛伊德Floyd算法

44. 蛤蟆的数据结构笔记之四十四弗洛伊德Floyd算法 本篇名言:"希望是厄运的忠实的姐妹. --普希金" 我们继续来看下数据结构图中的一个算法,这个算法来自图灵奖得主. 1.  Floyd算法介绍 Floyd算法又称为插点法,是一种用于寻找给定的加权图中多源点之间最短路径的算法.该算法名称以创始人之一.1978年图灵奖获得者.斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名.注意这个可不是心理学的那个弗洛伊德. 是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径

所有顶点之间的最短路径算法:Floyd算法。

Floyd算法的基本思想是:设集合S的初始状态为空,然后依次向集合S中加入顶点 0,1,...,n-1,每次加入一个顶点,用二维数组d保存各条最短路径的长度,其中d[i][j]存放的是顶点i到顶点j的最短路径的长度. 详细的说明: Floyd算法中最重要的办法为二维数组d[i][j],d[i][j]为从i到j中间只经过S中的顶点的.所有可能的路径中的最短路径的长度.如果从i到j通过S中的节点无法联通,则设置d[i][j]为正无穷.可以称d[i][j]存放的是从i到j的 当前最短路径 的长度.而随

最短路径之Floyd算法

Floyd算法又称弗洛伊德算法,也叫做Floyd's algorithm,Roy–Warshall algorithm,Roy–Floyd algorithm, WFI algorithm. Floyd算法是一种在有权图中(有确定的非负的权值,不能存在环路)查找最短路径的算法.该算法的一次简单执行可以找出任意结点之间的最短路径(尽管它没有返回路径的具体信息). 思想: Floyd算法通过比较图中任意两点间所有可能存在的路径长度得到最短路径长度. 我们定义一个函数shortestPath(i,j,