中国大学MOOC-陈越、何钦铭-数据结构-2018秋——公路村村通

版权声明:我的GitHub:https://github.com/617076674。真诚求星! https://blog.csdn.net/qq_41231926/article/details/84674573

我的中国大学MOOC-陈越、何钦铭-数据结构-2018秋代码仓:https://github.com/617076674/MOOC-DataStructure-2018-Autumn

题目描述:

知识点:最小生成树

思路一:prim算法

prim算法的具体实现:

prim算法需要实现两个关键的概念,即集合S的实现、顶点Vi(1 <= i <= N)与集合S的最短距离。

(1)集合S的实现方法和Dijkstra中相同,即使用一个bool型数组visited[]表示顶点是否已被访问。其中visited[i] == true表示顶点Vi已被访问,visited[i] == false表示顶点Vi未被访问。

(2)令int型数组d[]来存放顶点Vi(1 <= i <= N)与集合S的最短距离。初始时除了起点s的d[s]赋为0,其余顶点都赋为一个很大的数来表示INF,即不可达。

时间复杂度是O(N ^ 2)。空间复杂度是O(N + M)。

C++代码:

#include<iostream>
#include<vector>

using namespace std;

struct node{
	int v, price;
	node(int _v, int _price){
		v = _v;
		price = _price;
	}
};

int N, M, d[1001], INF = 1000000000;
vector<node> graph[1001];
bool visited[1001];

int prim(); 

int main(){
	scanf("%d %d", &N, &M);
	fill(visited + 1, visited + N + 1, false);
	fill(d + 1, d + N + 1, INF);
	int v1, v2, price;
	for(int i = 0; i < M; i++){
		scanf("%d %d %d", &v1, &v2, &price);
		graph[v1].push_back(node(v2, price));
		graph[v2].push_back(node(v1, price));
	}
	int result = prim();
	printf("%d\n", result);
	return 0;
}

int prim(){
	d[1] = 0;
	int ans = 0;
	for(int i = 0; i < N ; i++){
		int u = -1, min = INF;
		for(int j = 1; j <= N; j++){
			if(!visited[j] && d[j] < min){
				u = j;
				min = d[j];
			}
		}
		if(u == -1){
			return -1;
		}
		d[u] = min;
		visited[u] = true;
		ans += d[u];
		for(int j = 0; j < graph[u].size(); j++){
			int v = graph[u][j].v;
			int len = graph[u][j].price;
			if(!visited[v] && len < d[v]){
				d[v] = len;
			}
		}
	}
	return ans;
}

C++解题报告:

思路二:kruskal算法

kruskal算法的基本思想为:在初始状态隐去图中的所有边,这样图中每个顶点都自成一个连通块。之后执行下面的步骤:

(1)对所有边按边权从小到大进行排序。

(2)按边权从小到大测试所有边,如果当前测试边所连接的两个顶点不在一个连通块中,则把这条测试边加入当前最小生成树中;否则,将边舍弃。

(3)执行步骤(2),直到最小生成树中的边数等于总顶点数减1或是测试完所有边时结束。而当结束时如果最小生成树的边数小于总顶点数减1,说明该图不连通,返回-1。

时间复杂度是O(MlogM)。空间复杂度是O(M)。

C++代码:

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

struct edge{
	int u, v, cost;
	edge(int _u, int _v, int _cost){
		u = _u;
		v = _v;
		cost = _cost;
	}
};

int N, M;
vector<edge> edges;
int father[1001]; 

int findFather(int x);
int kruskal();
bool cmp(edge e1, edge e2);

int main(){
	scanf("%d %d", &N, &M);
	for(int i = 1; i <= N; i++){
		father[i] = i;
	}
	int v1, v2, cost;
	for(int i = 0; i < M; i++){
		scanf("%d %d %d", &v1, &v2, &cost);
		edges.push_back(edge(v1, v2, cost));
	}
	int result = kruskal();
	printf("%d\n", result);
	return 0;
} 

int findFather(int x){
	int a = x;
	while(x != father[x]){
		x = father[x];
	}
	while(a != father[a]){
		int z = a;
		a = father[a];
		father[z] = x;
	}
	return x;
}

int kruskal(){
	int ans = 0, num_edge = 0;
	sort(edges.begin(), edges.end(), cmp);
	for(int i = 0; i < M; i++){
		int uFather = findFather(edges[i].u);
		int vFather = findFather(edges[i].v);
		if(uFather != vFather){
			father[uFather] = vFather;
			ans += edges[i].cost;
			num_edge++;
			if(num_edge == N - 1){
				break;
			}
		}
	}
	if(num_edge != N - 1){
		return -1;
	}
	return ans;
}

bool cmp(edge e1, edge e2){
	return e1.cost < e2.cost;
}

C++解题报告:

猜你喜欢

转载自blog.csdn.net/qq_41231926/article/details/84674573