算法分析与设计作业1

1.问题
举一个实例,画出采用Prim算法构造最小生成树的过程,并按实验报告模板编写算法。
举一个实例,画出采用Kruskal算法构造最小生成树的过程,并按实验报告模板编写算法。
2.解析
在一给定的无向图G = (V,E) 中,(u,v) 代表连接顶点u与顶点v的边,w(u, v) 代表此边的权,若存在 T 为 E 的子集且为无循环图,使得的 w(T) 最小,则此 T 为 G 的最小生成树。
Prim算法:
设最小生成树中的点的集合是U,开始时最小生成树为空,所以U为空。

在这里插入图片描述
Kruskal算法:
设最小生成树中边的集合为T,开始时最小生成树为空,所以T为空。

在这里插入图片描述
3.设计

Prime:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<map>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<set>
#include<cctype>
#include<string>
#include<stdexcept>
#include<fstream>
#include<sstream>
#include<sstream>
#define mem(a,b) memset(a,b,sizeof(a))
#define debug() puts("what the fuck!")
#define dedebug() puts("what the fuck!!!")
#define ll long long
#define ull unsigned long long
#define speed {ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); };
using namespace std;
const double PI = acos(-1.0);
const int maxn = 2e5 + 10;
const int N = 2e3 + 10;
const ll INF = 1e18;
const ll mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const double esp_0 = 1e-6;
const double gold = (1 + sqrt(5)) / 2;
inline int rd() {
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch>'9') {
		if (ch == '-')f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
}
ll quick(ll a, ll b) {
	ll ans = 1;
	while (b) {
		if (b % 2) {
			ans = ans * a % mod;
		}
		b >>= 1;
		a = a * a % mod;
	}
	return ans % mod;
}
ll gcd(ll x, ll y) {
	return y ? gcd(y, x % y) : x;
}
int n, m;
int g[110][110];
int dis[110];
int vis[110];
int prim() {
	memset(vis, 0, sizeof vis);//标记数组
	memset(dis, inf, sizeof dis);//最小生成树节点间距离
	dis[1] = 0;
	for (int i = 1; i < m; ++i) {
		int pos = 0;
		for (int j = 1; j <= m; ++j) {
			if (!vis[j] && (pos == 0 || dis[j] < dis[pos]))pos = j;
		}
		vis[pos] = 1;
		for (int j = 1; j <= m; ++j) {
			if (!vis[j])dis[j] = min(dis[j], g[pos][j]);
		}
	}
	int ans = 0;
	for (int i = 1; i <= m; ++i) {
		if (dis[i] == inf)return -1;//如果有一个点的dis值为inf,说明该点被孤立,原图不存在最小生成树
		ans += dis[i];
	}
	return ans;//返回权值和
}
signed main() {
	scanf("%d%d", &n, &m);
	memset(g, inf, sizeof g);
	for (int i = 1; i <= n; ++i) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		g[u][v] = g[v][u] = w;
	}
	int ans = prim();
	cout << ans << endl;
	return 0;
}

kruskal:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<map>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<set>
#include<cctype>
#include<string>
#include<stdexcept>
#include<fstream>
#include<sstream>
#include<sstream>
#define mem(a,b) memset(a,b,sizeof(a))
#define debug() puts("what the fuck!")
#define dedebug() puts("what the fuck!!!")
#define ll long long
#define ull unsigned long long
#define speed {ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); };
using namespace std;
const double PI = acos(-1.0);
const int maxn = 2e5 + 10;
const int N = 2e3 + 10;
const ll INF = 1e18;
const ll mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const double esp_0 = 1e-6;
const double gold = (1 + sqrt(5)) / 2;
inline int rd() {
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch>'9') {
		if (ch == '-')f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
}
ll quick(ll a, ll b) {
	ll ans = 1;
	while (b) {
		if (b % 2) {
			ans = ans * a % mod;
		}
		b >>= 1;
		a = a * a % mod;
	}
	return ans % mod;
}
ll gcd(ll x, ll y) {
	return y ? gcd(y, x % y) : x;
}
struct Edge {
	int u, v, w;
	Edge() {};
	Edge(int u, int v, int w) :u(u), v(v), w(w) {};
	bool operator<(const Edge& a) {
		return w < a.w;
	}
}edge[110];
int n, m;
int fa[110];
void init() {
	for (int i = 1; i <= m; ++i)fa[i] = i;
}
int find(int x) {
	return fa[x] == x ? x : find(fa[x]);
}
int uni(int x, int y) {
	int fx = find(x);
	int fy = find(y);
	if (fx != fy) {
		fa[fx] = fy;
		return 1;
	}
	return 0;
}
int kruskal() {
	int ans = 0;
	init();
	sort(edge + 1, edge + 1 + n);
	for (int i = 1; i <= n; ++i) {
		if (uni(edge[i].u, edge[i].v))
			ans += edge[i].w;
	}
	return ans;
}
signed main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		edge[i] = Edge(u, v, w);
	}
	printf("%d\n", kruskal());
	return 0;
}

4.分析
prim:
未使用优先队列优化,需要遍历每一个点O(V2),并进行累加O(V),时间复杂度总共为O(V2+V),约为O(V2)
kruskal:对边排序时间复杂度约为O(Elog2E),并查集操作O(E),共为O(Elog2E+E),则约为O(Elog2E)

5.GitHub源码
prim
kruskal

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值