The Unique MST POJ - 1679 最小生成树(Kruskal算法+最小生成树唯一性判断)

  • The Unique MST

题目链接:http://poj.org/problem?id=1679

Given a connected undirected graph, tell if its minimum spanning tree is unique. 

Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the following properties: 
1. V' = V. 
2. T is connected and acyclic. 

Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E') of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E'. 

Input

The first line contains a single integer t (1 <= t <= 20), the number of test cases. Each case represents a graph. It begins with a line containing two integers n and m (1 <= n <= 100), the number of nodes and edges. Each of the following m lines contains a triple (xi, yi, wi), indicating that xi and yi are connected by an edge with weight = wi. For any two nodes, there is at most one edge connecting them.

Output

For each input, if the MST is unique, print the total cost of it, or otherwise print the string 'Not Unique!'.

题意:给你一张图,判断其最小生成树是否唯一。

思路:首先,记录边与边之间是否有权值相同的边,之后先求出最小生成树,同时记录最小生成树的所有边,依次将有相同权值且为最小生成树上的边去掉,再求出去掉后的最小生成树,每次求出后将当前求出的最小生成树的权值和第一次求出的比较,如果一样则说明最小生成树不唯一。

其实也可以理解为求次小生成树。

AC代码:

63ms

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<vector>
const int INF = 0x7fffffff;
const int MAXN = 1e5 + 7;
typedef long long ll;
using namespace std;
int n, m;
struct edge {
	int u, v,cost;
	int used,del,eq;
}e[MAXN];
int pre[MAXN];
int ans;
int sum;
bool cmp(edge a, edge b);
int find(int x);
void Union(int a,int b);
bool kruskal();
int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		ans = 0;
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= m; ++i) {
			scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].cost);
			e[i].used = 0;
			e[i].eq = 0;
			e[i].del = 0;
		}
		for (int i = 1; i <= m; ++i) {
			for (int j = 1; j <= m; ++j) {
				if (i == j)
					continue;
				if (e[i].cost == e[j].cost)
					e[i].eq=1;
			}
		}
		if (kruskal())
			printf("%d\n", ans);
		else
			printf("Not Unique!\n");
	}
	return 0;
}

bool cmp(edge a, edge b) {
	return a.cost < b.cost;
}

int find(int x) {
	if (pre[x] == x)
		return x;
	return pre[x] = find(pre[x]);
}

void Union(int a,int b){
	int x = find(a);
	int y = find(b);
	if (x == y)
		return;
	else
		pre[y] = x;
}

bool kruskal() {
	for (int i = 1; i <= n; ++i) {
		pre[i] = i;
	}
	sort(e + 1, e + 1 + m, cmp);
	for (int i = 1; i <= m; ++i) {
		if (find(e[i].u) != find(e[i].v)) {
			Union(e[i].u, e[i].v);
			ans += e[i].cost;
			e[i].used = 1;
		}
	}
	for (int i = 1; i <= m; ++i) {
		int cur = 0;
		if (e[i].used && e[i].eq) {
			e[i].del = 1;
			for (int i = 1; i <= n; ++i) {
				pre[i] = i;
			}
			for (int j = 1; j <= m; ++j) {
				if (e[j].del)
					continue;
				if (find(e[j].u) != find(e[j].v)) {
					Union(e[j].u, e[j].v);
					cur += e[j].cost;
				}
			}
			if (cur == ans)
				return false;
			e[i].del = 0;
		}
	}
	return true;
}

猜你喜欢

转载自blog.csdn.net/weixin_43821265/article/details/87206852