資料結構圖的最短路徑問題
阿新 • • 發佈:2018-11-25
07-圖4 哈利·波特的考試 (25 point(s))
哈利·波特要考試了,他需要你的幫助。這門課學的是用魔咒將一種動物變成另一種動物的本事。例如將貓變成老鼠的魔咒是haha,將老鼠變成魚的魔咒是hehe等等。反方向變化的魔咒就是簡單地將原來的魔咒倒過來念,例如ahah可以將老鼠變成貓。另外,如果想把貓變成魚,可以通過念一個直接魔咒lalala,也可以將貓變老鼠、老鼠變魚的魔咒連起來念:hahahehe。
現在哈利·波特的手裡有一本教材,裡面列出了所有的變形魔咒和能變的動物。老師允許他自己帶一隻動物去考場,要考察他把這隻動物變成任意一隻指定動物的本事。於是他來問你:帶什麼動物去可以讓最難變的那種動物(即該動物變為哈利·波特自己帶去的動物所需要的魔咒最長)需要的魔咒最短?例如:如果只有貓、鼠、魚,則顯然哈利·波特應該帶鼠去,因為鼠變成另外兩種動物都只需要念4個字元;而如果帶貓去,則至少需要念6個字元才能把貓變成魚;同理,帶魚去也不是最好的選擇。
輸入格式:
輸入說明:輸入第1行給出兩個正整數N (≤100)和M,其中N是考試涉及的動物總數,M是用於直接變形的魔咒條數。為簡單起見,我們將動物按1~N編號。隨後M行,每行給出了3個正整數,分別是兩種動物的編號、以及它們之間變形需要的魔咒的長度(≤100),數字之間用空格分隔。
輸出格式:
輸出哈利·波特應該帶去考場的動物的編號、以及最長的變形魔咒的長度,中間以空格分隔。如果只帶1只動物是不可能完成所有變形要求的,則輸出0。如果有若干只動物都可以備選,則輸出編號最小的那隻。
輸入樣例:
6 11 3 4 70 1 2 1 5 4 50 2 6 50 5 6 60 1 3 70 4 6 60 3 6 80 5 1 100 2 4 60 5 2 80
輸出樣例:
4 70
首先定義圖和邊,用鄰接矩陣表示
#define MaxVertexNum 100 // 最大邊數 #define INFINITY 65535 typedef int WeightType; typedef struct GNode *PtrToNode; typedef PtrToNode MGraph; struct GNode { int Nv; // 頂點數 int Ne; // 邊數 WeightType G[MaxVertexNum][MaxVertexNum]; // 鄰接矩陣 }; typedef int Vertex; typedef struct ENode *PtrToENode; typedef PtrToENode Edge; struct ENode { Vertex V1, V2; WeightType Weight; };
建立一個無向圖所需的函式
MGraph CreateGraph(int VertexNum)
{
/* 初始化一個有VertexNum個頂點但沒有邊的圖*/
Vertex V, W;
MGraph Graph;
Graph = (MGraph)malloc(sizeof(struct GNode));
Graph->Nv = VertexNum;
Graph->Ne = 0;
for (V = 0; V < Graph->Nv; V++)
{
for (W = 0; W < Graph->Nv; W++)
{
Graph->G[V][W] = INFINITY;
}
}
return Graph;
}
void InserEdge(MGraph Graph, Edge E)
{
Graph->G[E->V1][E->V2] = E->Weight;
Graph->G[E->V2][E->V1] = E->Weight;
}
讀入資料,建立圖
MGraph BuildGraph()
{
MGraph Graph;
Edge E;
int Nv;
scanf("%d", &Nv); // 讀入頂點的個數
Graph = CreateGraph(Nv);
scanf("%d", &(Graph->Ne)); // 讀入邊數
if (Graph->Ne != 0)
{
E = (Edge)malloc(sizeof(struct ENode));
for (int i = 0; i < Graph->Ne; i++)
{
scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);
E->V1--; E->V2--; // 題目的編號輸入從1開始
InserEdge(Graph, E);
}
}
return Graph;
}
最短路徑Floyd演算法
void Floyd(MGraph Graph, WeightType D[][MaxVertexNum])
{
// 初始化
for (int i = 0; i < Graph->Nv; i++)
{
for (int j = 0; j < Graph->Nv; j++)
{
D[i][j] = Graph->G[i][j];
}
}
for (int k = 0; k < Graph->Nv; k++)
{
for (int i = 0; i < Graph->Nv; i++)
{
for (int j = 0; j < Graph->Nv; j++)
{
if (D[i][k] + D[k][j] < D[i][j])
{
D[i][j] = D[i][k] + D[k][j];
}
}
}
}
}
WeightType FindMaxDist(WeightType D[][MaxVertexNum], Vertex i, int N)
{
/* 根據路徑矩陣D找出N個頂點中,頂點i的最大路徑 */
WeightType MaxDist = 0;
for (int j = 0; j < N; j++)
{
if (i != j && D[i][j] > MaxDist)
MaxDist = D[i][j];
}
return MaxDist;
}
求所有點中最大路徑的最小值
void FindAnimal(MGraph Graph)
{
WeightType D[MaxVertexNum][MaxVertexNum], MaxDist, MinDist;
Vertex Animal;
Floyd(Graph, D);
MinDist = INFINITY;
for (int i = 0; i < Graph->Nv; i++)
{
MaxDist = FindMaxDist(D, i, Graph->Nv);
if (MaxDist == INFINITY)
{
/*說明有從i無法變出的動物*/
printf("0\n");
return;
}
if (MinDist > MaxDist)
{
MinDist = MaxDist;
Animal = i + 1;
}
}
printf("%d %d\n", Animal, MinDist);
}
主函式
int main()
{
MGraph G = BuildGraph();
FindAnimal(G);
return 0;
}