设a、b、c、d、e、f表示一个乡的6个村庄,弧上的权值表 示两村之间的距离。现要在这6个村庄中选择一个村庄建一所医院,问医院建在哪个村庄 才能使离医院最远的村庄到医院的距离最短?
输入的第一行为村庄个数
输入的其他是多个存在组成网络的邻接矩阵表示
输出医院建立的位置
在这里给出一组输入。例如:
- 6
- 0 12 3 65535 9 10
- 12 0 65535 2 6 65535
- 3 65535 0 2 65535 6
- 65535 2 2 0 4 7
- 9 6 65535 4 0 4
- 10 65535 6 7 4 0
在这里给出相应的输出。例如:
c
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
解题思路:本体要求找到一个地点建医院,算出这个医院距离其它每个结点的最小距离,然后找到每个出发点这些最小距离中最远的那个作比较。找到最远距离最小的那个输出。
由于要用到最小路径,需要迪杰斯特拉算法
1.先对需要的东西进行定义
- #define bool char
- #define true 1
- #define false 0
-
- typedef char VerTexType; //字符型顶点数据类型
- typedef int ArcType; //边的权值类型为整型
- #define MVNum 100 //最大顶点数
- #define MaxInt 32767 //最大权值
2.图的结构,由于题中已经将邻接矩阵给出,所以不需要我们来自行创建
- //图的邻接矩阵存储表示
- typedef struct
- {
- VerTexType vexs[MVNum]; //顶点表
- ArcType arcs[MVNum][MVNum];//邻接矩阵
- int vexnum, arcnum; //节点数和边数
- }AMGraph;
-
- //输入题中给的邻接矩阵
- void Scanf(AMGraph* G, int n)
- {
- int i, j;
- for(i = 0; i < n; i++)
- for(j = 0; j < n; j++)
- scanf("%d", &G->arcs[i][j]);
- G->vexnum = n;
- }
3.迪杰斯特拉算法,其中D数组存放了起点v0到其他各个点位的最短距离,找到最大值返回。
算法简介:
1.初始化:
(1)创建S数组存放结点被选中的情况,选过为True,没选为False;初始化时先全部置为False。
(2)创建D数组存放到达从起点出发,到达其他顶点的距离,根据路径的发展,更小的权值会替换大的权值。初始化时先把出发点v0到其他结点的边赋给D。
(3)创建Path数组存放每个结点的上一个结点(前置结点),通常用来遍历最短路径,本题虽然不需要用到,但还是写上了。 初始化时都置为-1代表没有边连接上一个。
(4)开始时把出发点v0的S[v0]改为True代表选过了,起点到自己的距离D[v0] = 0;
2.找到各个最小路径
(1)从第一个结点到最后一个结点都要找一次起点到它的最短路径,这是最外一层循环
(2)在当前的D数组中找到最小权值的边,记录下来用以链接到该边连接的下一个结点
(3)把新选出结点的S数组置为True,并且将新结点带来的新路径(边)和之前的路径权值进行比较,比之前小就替换掉D数组中对应的值,再将新结点的前置结点设置为上一个结点。
3.返回每组中最远值
- int Dijkstra(AMGraph G, int v0)
- {
- //S放是否选中过,D放起点距离其他点的距离,path放前驱结点,n是顶点个数
- int S[6], D[6], Path[6];
- int n = 6, i, w, v;
-
- //初始化
- for(v = 0; v < n; v++)
- {
- S[v] = false; //先把S都置为未选中过
- D[v] = G.arcs[v0][v]; //把顶点距离其他结点的距离输入
- if(D[v] < MaxInt) Path[v] = v0; //如果v0到v有边,那就把v的前置结点写上
- else Path[v] = -1; //如果没边,就把前置结点设置为-1代表没有
- }
- S[v0] = true; //起点设为选中过
- D[v0] = 0; //起点到自己的距离为0
-
- //开始找最小距离
- int min;
- for(i = 1; i < n; i++)
- {
- min = MaxInt;
- for(w = 0; w < n; w++)
- {
- //没被选中 并且有边的 结点
- if(!S[w] && D[w] < min)
- {
- //就记录下结点的位置
- v = w;
- //并把它的权值暂存为最小权值
- min = D[w];
- }
- }
- //最小边的结点改为被选中
- S[v] = true;
- //从新选中的结点开始寻找,
- for(w = 0; w < n; w++)
- {
- //未被选中,并且从起始节点到目前能到达的结点的最小值
- if(!S[w] && D[v] + G.arcs[v][w] < D[w])
- {
- //总长度 = 之前长度的总和+到新结点的长度
- D[w] = D[v] + G.arcs[v][w];
- //新结点的前置结点设置
- Path[w] = v;
- }
- }
- }
- //找到每组最远的那个
- int max = 0;
- for(int s = 0; s < 6; s++)
- {
- if(max < D[s])
- max = D[s];
- }
-
- return max;
- }
4.主函数,因为本体条件是固定的,所以很多地方的大小我便直接写了6。
- int main()
- {
- //输入
- AMGraph G;
- int n;
- scanf("%d",&n);
- Scanf(&G, n);
-
- int temp[6];
- int min = 0;
- //先把每组的最远距离搞出来
- for(int i = 0; i < 6; i++)
- {
- temp[i] = Dijkstra(G, i);
- }
- //找最远距离中最小的
- for(int i = 0; i < 6; i++)
- {
- if(temp[min]>temp[i])
- min = i;
- }
- //转换字符
- char name = (char)min+97;
- printf("%c",name);
-
-
- return 0;
- }
5.全部代码
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
-
- #define bool char
- #define true 1
- #define false 0
-
- typedef char VerTexType; //字符型顶点数据类型
- typedef int ArcType; //边的权值类型为整型
- #define MVNum 100 //最大顶点数
- #define MaxInt 32767 //最大权值
-
- //辅助数组,用来记录从顶点集到
- struct
- {
- VerTexType adjvex;
- ArcType lowcost;
- } closedge[MVNum];
-
- //图的邻接矩阵存储表示
- typedef struct
- {
- VerTexType vexs[MVNum]; //顶点表
- ArcType arcs[MVNum][MVNum];//邻接矩阵
- int vexnum, arcnum; //节点数和边数
- }AMGraph;
-
- //找到出发点得位置
- int LocateVex(AMGraph* G, VerTexType v)
- {
- for(int i = 0; i < G->vexnum; i++)
- {
- if(G->vexs[i] == v)
- return i;
- }
- return -1;
- }
-
- //输入题中给的邻接矩阵
- void Scanf(AMGraph* G, int n)
- {
- int i, j;
- for(i = 0; i < n; i++)
- for(j = 0; j < n; j++)
- scanf("%d", &G->arcs[i][j]);
- G->vexnum = n;
- }
-
- //测试用
- void Print(AMGraph G)
- {
- int i, j;
- for(i = 0; i < G.vexnum; i++)
- {
- for(j = 0; j < G.vexnum; j++)
- printf("%d ", G.arcs[i][j]);
- printf("\n");
- }
-
- }
-
- //从每个顶点出发,找最短路径
-
-
- int Dijkstra(AMGraph G, int v0)
- {
- //S放是否选中过,D放起点距离其他点的距离,path放前驱结点,n是顶点个数
- int S[6], D[6], Path[6];
- int n = 6, i, w, v;
-
- //初始化
- for(v = 0; v < n; v++)
- {
- S[v] = false; //先把S都置为未选中过
- D[v] = G.arcs[v0][v]; //把顶点距离其他结点的距离输入
- if(D[v] < MaxInt) Path[v] = v0; //如果v0到v有边,那就把v的前置结点写上
- else Path[v] = -1; //如果没边,就把前置结点设置为-1代表没有
- }
- S[v0] = true; //起点设为选中过
- D[v0] = 0; //起点到自己的距离为0
-
- //开始找最小距离
- int min;
- for(i = 1; i < n; i++)
- {
- min = MaxInt;
- for(w = 0; w < n; w++)
- {
- //没被选中 并且有边的 结点
- if(!S[w] && D[w] < min)
- {
- //就记录下结点的位置
- v = w;
- //并把它的权值暂存为最小权值
- min = D[w];
- }
- }
- //最小边的结点改为被选中
- S[v] = true;
- //从新选中的结点开始寻找,
- for(w = 0; w < n; w++)
- {
- //未被选中,并且从起始节点到目前能到达的结点的最小值
- if(!S[w] && D[v] + G.arcs[v][w] < D[w])
- {
- //总长度 = 之前长度的总和+到新结点的长度
- D[w] = D[v] + G.arcs[v][w];
- //新结点的前置结点设置
- Path[w] = v;
- }
- }
- }
- //找到每组最远的那个
- int max = 0;
- for(int s = 0; s < 6; s++)
- {
- if(max < D[s])
- max = D[s];
- }
-
- return max;
- }
-
-
-
-
- int main()
- {
- //输入
- AMGraph G;
- int n;
- scanf("%d",&n);
- Scanf(&G, n);
-
- int temp[6];
- int min = 0;
- //先把每组的最远距离搞出来
- for(int i = 0; i < 6; i++)
- {
- temp[i] = Dijkstra(G, i);
- }
- //找最远距离中最小的
- for(int i = 0; i < 6; i++)
- {
- if(temp[min]>temp[i])
- min = i;
- }
- //转换字符
- char name = (char)min+97;
- printf("%c",name);
-
-
- return 0;
- }