HDU 1233 还是畅通工程 解题报告 最小生成树

HDU 1233 还是畅通工程 解题报告

解题思路:最小生成树基本题,我两种方法都写了一下,看注释吧。
1.prim算法。这个算法核心思想就是从第一个点开始建树,每次找离树最近的点加入树。
在这里插入图片描述

#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<map>
#include<stack>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<fstream>
#include<iomanip>
#include<vector>
#pragma warning(disable:4996)
#define INF 0x3f3f3f3f
#define ll long long
#define PI acos(-1.0)
const int N = 200010;
const int maxn = 1e5+10;
using namespace std;
int  d[105];//放每个点到树的最短距离
int visit[105];
int edge[105][105];
void prim(int n)
{
	for (int i = 1; i <= n; i++)//一开始的树就是一个点
		d[i] = edge[1][i];
	int ans = 0;
	d[1] = 0;
	visit[1] = 1;
	for (int i = 2; i <= n; i++)//进行n-1次操作,i只是计数用
	{
		int u = INF;
		int pos;
		for (int j = 1; j <= n; j++)
		{
			if (!visit[j] && u > d[j])//每次都在没用过的点中找与已建成的树距离最短的点
			{
				u = d[j];
				pos = j;
			}
		}
		visit[pos] = 1;
		ans += u;
		for (int j = 1; j <= n; j++)
		{
			if (!visit[j] && d[j] > edge[pos][j])
			{
				d[j] = edge[pos][j];//更新没用过的点到树的最短距离
			}
		}
	}
	printf("%d\n", ans);
}
int main()
{
	int n;
	while (~scanf("%d", &n) && n)
	{
		memset(visit, 0, sizeof(visit));
		int m = (n - 1) * n / 2;
		int u, v, w;
		while (m--)
		{
			scanf("%d%d%d", &u, &v, &w);
			edge[u][v] = edge[v][u] = w;//注意是无向图
		}
		prim(n);
	}
	return 0;
}



2.kruskal算法。这个算法的核心思想在于每次连接森林里最近的两个未连通的点,最后成树。
在这里插入图片描述

#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<map>
#include<stack>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<fstream>
#include<iomanip>
#include<vector>
#pragma warning(disable:4996)
#define INF 0x3f3f3f3f
#define ll long long
#define PI acos(-1.0)
const int N = 200010;
const int maxn = 1e5+10;
using namespace std;
int father[maxn];
struct node {
	int u, v, val;
}edge[maxn];
bool cmp(node a, node b)
{
	return a.val < b.val;
}
int find(int x)
{
	if (x == father[x])
		return x;
	else
		return father[x] = find(father[x]);
}
void kruskal(int n, int m)
{
	sort(edge + 1, edge + m + 1, cmp);
	for (int i = 1; i <= n; i++)
		father[i] = i;
	int ans = 0;
	for (int i = 1; i <= m; i++)
	{
		int a = find(edge[i].u);
		int b = find(edge[i].v);
		if (a != b)//用并查集的方式判断两个点是否连通
		{
			father[a]=b;
			ans += edge[i].val;
		}
	}
	printf("%d\n", ans);
}
int main()
{
	int n;
	while (~scanf("%d", &n) && n)
	{
		int m = (n - 1) * n / 2;
		for (int i = 1; i <= m; i++)
		{
			scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].val);
		}
		kruskal(n, m);
	}
	return 0;
}



发布了64 篇原创文章 · 获赞 0 · 访问量 1443

猜你喜欢

转载自blog.csdn.net/weixin_45566331/article/details/104928733