案例6-1.7 公路村村通 (30分)
现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。
输入格式:
输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。
输出格式:
输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。
输入样例:
6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3
输出样例:
12
一.Prim算法
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MaxVertexNum 1000
#define INFINITY 65535
#define ERROR -1
typedef struct GNode* PtrToGNode;
struct GNode {
int Nv, Ne;
int G[MaxVertexNum][MaxVertexNum];
};
typedef PtrToGNode MGraph;
typedef struct ENode* PtrToENode;
struct ENode {
int V1, V2;
int Weight;
};
typedef PtrToENode Edge;
MGraph CreateGraph(int VertexNum) {
int v, w;
MGraph Graph = (MGraph)malloc(sizeof(struct GNode));
Graph->Nv = VertexNum;
Graph->Ne = 0;
for (v = 1; v <= Graph->Nv; v++)
for (w = 1; w <= Graph->Nv; w++)
Graph->G[v][w] = INFINITY;
return Graph;
}
void InsertEdge(MGraph Graph, Edge E) {
Graph->G[E->V1][E->V2] = E->Weight;
Graph->G[E->V2][E->V1] = E->Weight;
}
int FindMinDist(MGraph Graph, int dist[]) {
int MinV, V;
int MinDist = INFINITY;
for (V = 1; V <= Graph->Nv; V++) {
if (dist[V] != 0 && dist[V] < MinDist) {
MinDist = dist[V];
MinV = V;
}
}
if (MinDist < INFINITY)return MinV;
else return ERROR;
}
int parent[MaxVertexNum];
int Prim(MGraph Graph, MGraph MST) {
int dist[MaxVertexNum], TotalWeight;
int V, W;
int VCount;
Edge E;
for (V = 1; V <= Graph->Nv; V++) {
dist[V] = Graph->G[1][V];
parent[V] = 1;
}
TotalWeight = 0;
VCount = 0;
E = (Edge)malloc(sizeof(struct ENode));
dist[1] = 0;
VCount++;
parent[1] = 1;
while (1) {
V = FindMinDist(Graph, dist);
if (V == ERROR)break;
E->V1 = parent[V];
E->V2 = V;
E->Weight = dist[V];
InsertEdge(MST, E);
TotalWeight += dist[V];
dist[V] = 0;
VCount++;
for (W = 1; W <= Graph->Nv; W++)
if (dist[W] != 0 && Graph->G[V][W] < INFINITY) {
if (Graph->G[V][W] < dist[W]) {
dist[W] = Graph->G[V][W];
parent[W] = V;
}
}
}
if (VCount < Graph->Nv)
TotalWeight = ERROR;
return TotalWeight;
}
int main() {
MGraph Graph, MST;
Edge E;
int V, TotalWeight;
int Nv, i;
scanf("%d", &Nv);
Graph = CreateGraph(Nv);
MST = CreateGraph(Nv);
scanf("%d", &(Graph->Ne));
if (Graph->Ne != 0) {
E = (Edge)malloc(sizeof(struct ENode));
for (i = 1; i <= Graph->Ne; i++) {
scanf("%d%d%d", &E->V1, &E->V2, &E->Weight);
InsertEdge(Graph, E);
}
}
TotalWeight = Prim(Graph,MST);
printf("%d", TotalWeight);
return 0;
}
二.Kruskal算法
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define MaxVertexNum 1000
typedef struct ENode* PtrToENode;
struct ENode {
int V1, V2;
int Weight;
};
typedef PtrToENode Edge;
typedef struct AdjVNode* PtrToAdjVNode;
struct AdjVNode {
int AdjV;
int Weight;
PtrToAdjVNode Next;
};
typedef struct VNode {
PtrToAdjVNode FirstEdge;
}AdjList[MaxVertexNum];
typedef struct GNode* PtrToGNode;
struct GNode {
int Nv;
int Ne;
AdjList G;
};
typedef PtrToGNode LGraph;
LGraph CreateGraph(int VertexNum) {
int V;
LGraph Graph = (LGraph)malloc(sizeof(struct GNode));
Graph->Nv = VertexNum;
Graph->Ne = 0;
for (V = 1; V <= Graph->Nv; V++)
Graph->G[V].FirstEdge = NULL;
return Graph;
}
void InsertEdge(LGraph Graph, Edge E) {
PtrToAdjVNode NewNode;
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV = E->V2;
NewNode->Weight = E->Weight;
NewNode->Next = Graph->G[E->V1].FirstEdge;
Graph->G[E->V1].FirstEdge = NewNode;
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV = E->V1;
NewNode->Weight = E->Weight;
NewNode->Next = Graph->G[E->V2].FirstEdge;
Graph->G[E->V2].FirstEdge = NewNode;
}
LGraph BuildGraph() {
LGraph Graph;
Edge E;
int Nv, i;
scanf("%d", &Nv);
Graph = CreateGraph(Nv);
scanf("%d", &(Graph->Ne));
if (Graph->Ne != 0) {
E = (Edge)malloc(sizeof(struct ENode));
for (i = 0; i < Graph->Ne; i++) {
scanf("%d%d%d", &E->V1, &E->V2, &E->Weight);
InsertEdge(Graph, E);
}
}
return Graph;
}
int SetType[MaxVertexNum];
void InitializeVSet(int S[], int N) {
int i;
for (i = 1; i <= N; i++) {
S[i] = -1;
}
}
void Union(int S[], int Root1, int Root2) {
if (S[Root1] > S[Root2]) {
S[Root2] += S[Root1];
S[Root1] = Root2;
}
else {
S[Root1] += S[Root2];
S[Root2] = Root1;
}
}
int Find(int S[], int X) {
if (S[X] < 0)
return X;
else
return S[X] = Find(S, S[X]);
}
bool CheckCycle(int* VSet, int V1, int V2) {
int Root1;
int Root2;
Root1 = Find(VSet, V1);
Root2 = Find(VSet, V2);
if (Root1 == Root2)
return false;
else {
Union(VSet, Root1, Root2);
return true;
}
}
void PercDown(Edge ESet, int p, int N) {
int Child, Parent;
struct ENode X = ESet[p];
for (Parent = p; (Parent * 2 + 1) < N; Parent = Child) {
Child = Parent * 2 + 1;
if (Child != N - 1 && ESet[Child].Weight > ESet[Child + 1].Weight)
Child++;
if (X.Weight <= ESet[Child].Weight)
break;
else {
ESet[Parent] = ESet[Child];
}
}
ESet[Parent] = X;
}
void InitializeESet(LGraph Graph, Edge ESet) {
int ECount = 0, V;
PtrToAdjVNode W;
for (V = 1; V < Graph->Nv; V++) {
for (W = Graph->G[V].FirstEdge; W; W = W->Next) {
if (V < W->AdjV) {/*避免重复录入无向边,只录入V1<V2的边*/
ESet[ECount].V1 = V;
ESet[ECount].V2 = W->AdjV;
ESet[ECount++].Weight = W->Weight;
}
}
}
for (ECount = Graph->Ne / 2 ; ECount > 0; ECount--) {
PercDown(ESet, ECount, Graph->Ne);
}
}
void Swap(Edge a, Edge b) {
struct ENode temp = *a;
*a = *b;
*b = temp;
}
int GetEdge(Edge ESet, int CurrentSize) {
Swap(&ESet[0], &ESet[CurrentSize - 1]);
PercDown(ESet, 0, CurrentSize - 1);
return CurrentSize - 1;
}
int Kruskal(LGraph Graph, LGraph MST) {
int TotalWeight;
int ECount;
int VSet[MaxVertexNum] = { 0 };
InitializeVSet(VSet, Graph->Nv);
Edge ESet = (Edge)malloc((Graph->Ne) * sizeof(struct ENode));
InitializeESet(Graph, ESet);
MST = CreateGraph(Graph->Nv);
TotalWeight = 0;
ECount = 0;
int NextEdge = Graph->Ne;
while (ECount < Graph->Nv - 1) {
NextEdge = GetEdge(ESet, NextEdge);
if (NextEdge < 0)
break;
if (CheckCycle(VSet, ESet[NextEdge].V1, ESet[NextEdge].V2)) {
InsertEdge(MST, ESet + NextEdge);
TotalWeight += ESet[NextEdge].Weight;
ECount++;
}
}
if (ECount < Graph->Nv - 1)
TotalWeight = -1;
else
return TotalWeight;
}
int main() {
LGraph Graph = BuildGraph();
LGraph MST = (LGraph)malloc(sizeof(LGraph));
int TotalWeight = Kruskal(Graph, MST);
printf("%d", TotalWeight);
system("pause");
return 0;
}