- 选址问题
【基本要求】
给定n个村庄之间的交通图。若村庄i和j之间有路可通,则i和j用边连接,边上的权值Wij表示这条道路的长度。
现打算在这n个村庄中选定一个村庄建一所医院。编写如下算法:
(1)求出该医院应建在哪个村庄,才能使距离医院最远的村庄到医院的路程最短。
(2)求出该医院应建在哪个村庄,能使其它所有村庄到医院的路径总和最短。
【提示】
对于问题(1),可以先求出每个村庄到其它所有村庄的最短路径,保存其最大值(表示假设医院建在该村庄,距离医院最远的村庄的路径长度);然后在这些最大值中找出一个最小值。
对于问题(2),可以先求出每个村庄到其它所有村庄的最短路径,保存其累加和(表示假设医院建在该村庄,其它所有村庄距离医院的路径总和);然后在这些和中找出一个最小值。
#include <stdio.h>
#include <stdlib.h>
#define MaxVertexNum 100
#define INFINITY 65535
typedef int DistType;
typedef int Vertex;
typedef int WeightType;
typedef char DataType;
typedef int ElementType;
typedef struct ENode
{
Vertex V1, V2;
WeightType Weight;
}*Edge;
typedef struct GNode
{
int Nv;
int Ne;
WeightType Weight[MaxVertexNum][MaxVertexNum];
DataType Data[MaxVertexNum];
}*MGraph;
MGraph CreateGraph(int VertexNum)
{
Vertex V, W;
MGraph Graph;
Graph = (MGraph)malloc(sizeof(GNode));
Graph->Nv = VertexNum;
Graph->Ne = 0;
for (V = 0; V <= Graph->Nv; V++)
for (W = 0; W <= Graph->Nv; W++)
Graph->Weight[V][W] = INFINITY;
return Graph;
}
void InsertEdge(MGraph Graph, Edge E)
{
Graph->Weight[E->V1][E->V2] = E->Weight;
Graph->Weight[E->V2][E->V1] = E->Weight;
}
MGraph BuildGraph()
{
MGraph Graph;
Edge E;
Vertex V;
int Nv, i;
scanf("%d", &Nv);
Graph = CreateGraph(Nv);
scanf("%d", &(Graph->Ne));
if (Graph->Ne != 0)
{
E = (Edge)malloc(sizeof(ENode));
for (i = 0; i < Graph->Ne; i++)
{
scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);
InsertEdge(Graph, E);
}
}
return Graph;
}
typedef struct TableNode
{
int Known;
DistType Distence;
Vertex Path;
}Table;
void InitTable(MGraph Graph, Table *T)
{
int i;
for (i = 0; i <= Graph->Nv; i++)
{
T[i].Distence = INFINITY;
T[i].Known = 0;
T[i].Path = 0;
}
}
Vertex FindMinDist(MGraph Graph, Table *T)
{
Vertex MinV, V;
int MinDist = INFINITY;
for (V = 0; V <= Graph->Nv; V++)
{
if (T[V].Known == 0 && T[V].Distence < MinDist)
{
MinDist = T[V].Distence;
MinV = V;
}
}
if (MinDist < INFINITY)
return MinV;
else
return -1;
}
void Dijkstra(MGraph Graph, Table *T)
{
Vertex V, W;
for (;;)
{
V = FindMinDist(Graph, T);
if (V == -1)
break;
T[V].Known = 1;
for (W = 0; W <= Graph->Nv; W++)
{
if (Graph->Weight[V][W] != INFINITY && T[W].Known == 0)
if (T[V].Distence + Graph->Weight[V][W] < T[W].Distence)
{
T[W].Distence = T[V].Distence + Graph->Weight[V][W];
T[W].Path = V;
}
}
}
}
void FindMaxPath(MGraph Graph,Table *T,int *MaxPath)
{
Vertex V;
static int i = 0;
int Max = 0;
for (V = 0; V < Graph->Nv; V++)
{
if (T[V].Distence > Max)
Max = T[V].Distence;
}
MaxPath[i++] = Max;
}
void FindTotalPath(MGraph Graph, Table *T, int *TotalPath)
{
Vertex V;
static int i = 0;
TotalPath[i] = 0;
for (V = 0; V < Graph->Nv; V++)
TotalPath[i] += T[V].Distence;
i++;
}
Vertex FindMin(int *A,int N)
{
int i, Min = 0;
for (i = 0; i < N; i++)
{
if (A[i] < A[Min])
Min = i;
}
return Min;
}
int main()
{
MGraph Graph = BuildGraph();
Table T[MaxVertexNum];
Vertex V, W;
int MaxPath[MaxVertexNum], TotalPath[MaxVertexNum];
for (V = 0; V < Graph->Nv; V++)
{
InitTable(Graph, T);
T[V].Distence = 0;
Dijkstra(Graph, T);
FindMaxPath(Graph, T, MaxPath);
FindTotalPath(Graph, T, TotalPath);
}
V = FindMin(MaxPath,Graph->Nv);
W = FindMin(TotalPath,Graph->Nv);
printf("医院应建在%d村庄,距离医院最远的村庄到医院的路程最短。\n", V);
printf("医院应建在%d村庄,其它所有村庄到医院的路径总和最短。\n", W);
}