1016. Uniqueness of MST (35)解题报告

原题链接:

1016. Uniqueness of MST (35)

解题思路:

运用Kruskal最小生成树算法。

  1. 用Kruskal最小生成树算法对输入数据进行操作;
  2. 算法输出连通分量只有1个,则存在最小生成树,否则不存在。
  3. 枚举最小生成树的每一条边,将该边从图中删去,然后对该图进行步骤1。
  4. 如果得到的最小生成树的总重等于步骤2得到最小生成树的总重,则最小生成树数量加一。
通过画面:
代码:
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
using namespace std;

struct edge {
	int start, dest, weight, index;
	edge(int start = 0, int dest = 0, int weight = 0) : start(start), dest(dest), weight(weight) 
	{
		index = 0;
	}
	bool operator<(const edge& e2) const
	{
		if (weight > e2.weight) {
			return true;
		}
		else if (weight == e2.weight && index > e2.index) {
			return true;
		}
		else {
			return false;
		}
	}
};
int kruskal(const vector<vector<edge>>& adjList, bool& flag, int& sumWeight);
bool kruskal(const vector<vector<edge>>& adjList, edge taboo, int min);
int findRoot(vector<int>& setArray, int index);
void unionSet(vector<int>& setArray, int root1, int root2);

int main()
{
	int n = 0, m = 0;
	assert(scanf("%d %d", &n, &m) == 2);
	vector<vector<edge>> adjList(n + 1);
	for (int i = 0; i < m; i++) {
		edge tmp;
		assert(3 == scanf("%d %d %d", &tmp.start, &tmp.dest, &tmp.weight));
		tmp.index = i;
		adjList[tmp.start].push_back(tmp);
	}
	bool flag = true;
	int sumWeight = 0;
	int component = kruskal(adjList, flag, sumWeight);
	if (component > 1) {
		printf("No MST\n%d\n", component);
	}
	else {
		printf("%d\n", sumWeight);
		if (flag) {
			puts("Yes");
		}
		else {
			puts("No");
		}
	}
	return 0;
}

int kruskal(const vector<vector<edge>>& adjList, bool& flag, int& sumWeight)
{
	vector<int> setArray(adjList.size(), -1);
	priority_queue<edge> edgeLeft;
	vector<edge> MST;
	for (int i = 0; i < (int)adjList.size(); i++) {
		for (int j = 0; j < (int)adjList[i].size(); j++) {
			edgeLeft.push(adjList[i][j]);
		}
	}
	int cnt = adjList.size() - 2;
	while (cnt && !edgeLeft.empty()) {
		edge tmp = edgeLeft.top();
		edgeLeft.pop();
		int root1 = findRoot(setArray, tmp.start);
		int root2 = findRoot(setArray, tmp.dest);
		if (root1 != root2) {
			cnt--;
			unionSet(setArray, root1, root2);
			sumWeight += tmp.weight;
			MST.push_back(tmp);
		}
	}
	for (int i = 0; i < (int)MST.size() && flag; i++) {
		flag = kruskal(adjList, MST[i], sumWeight);
	}
	return cnt + 1;
}
bool kruskal(const vector<vector<edge>>& adjList, edge taboo, int min)
{
	vector<int> setArray(adjList.size(), -1);
	priority_queue<edge> edgeLeft;
	for (int i = 0; i < (int)adjList.size(); i++) {
		for (int j = 0; j < (int)adjList[i].size(); j++) {
			if (taboo.index != adjList[i][j].index) {
				edgeLeft.push(adjList[i][j]);
			}
		}
	}
	int cnt = adjList.size() - 2;
	int totalWeight = 0;
	while (cnt && !edgeLeft.empty()) {
		edge tmp = edgeLeft.top();
		edgeLeft.pop();
		int root1 = findRoot(setArray, tmp.start);
		int root2 = findRoot(setArray, tmp.dest);
		if (root1 != root2) {
			cnt--;
			unionSet(setArray, root1, root2);
			totalWeight += tmp.weight;
		}
	}
	if (cnt > 0) {
		return true;
	}
	else if (min != totalWeight) {
		return true;
	}
	else {
		return false;
	}
}

int findRoot(vector<int>& setArray, int index)
{
	if (setArray[index] < 0) {
		return index;
	}
	else {
		return setArray[index] = findRoot(setArray, setArray[index]);
	}
}
void unionSet(vector<int>& setArray, int root1, int root2)
{
	if (setArray[root1] < setArray[root2]) {
		setArray[root1] += setArray[root2];
		setArray[root2] = root1;
	}
	else {
		setArray[root2] += setArray[root1];
		setArray[root1] = root2;
	}
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值