C语言实现Prim算法与Kruskal算法(浙大 陈越版)

案例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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值