最小生成树的唯一性

进阶实验6-3.6 最小生成树的唯一性 (35 分)

给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。

输入格式:

首先第一行给出两个整数:无向图中顶点数 N(≤500)和边数 M。随后 M 行,每行给出一条边的两个端点和权重,格式为“顶点1 顶点2 权重”,其中顶点从 1 到N 编号,权重为正整数。题目保证最小生成树的总权重不会超过 2​30​​。

输出格式:

如果存在最小生成树,首先在第一行输出其总权重,第二行输出“Yes”,如果此树唯一,否则输出“No”。如果树不存在,则首先在第一行输出“No MST”,第二行输出图的连通集个数。

输入样例 1:

5 7
1 2 6
5 1 1
2 3 4
3 4 3
4 1 7
2 4 2
4 5 5

输出样例 1:

11
Yes

输入样例 2:

4 5
1 2 1
2 3 1
3 4 2
4 1 2
3 1 3

输出样例 2:

4
No

输入样例 3:

5 5
1 2 1
2 3 1
3 4 2
4 1 2
3 1 3

输出样例 3:

No MST
2
#include<stdio.h>
#include<stdlib.h>

struct Edge {
	int Vertex1;
	int Vertex2;
	int Weight;
	int Flag;
};

int* InitializeUnion(int N);
void Combine(int* a, int Root1, int Root2);
int FindRoot(int* a, int Item);
int Kruskal(int N, int M);
#include<algorithm>
using namespace std;
struct EdgeRule {
	bool operator()(const struct Edge& E1, const struct Edge& E2) {
		return E1.Weight < E2.Weight;
	}
};
int Work(int N, struct Edge* EdgeSet, int* Union, int th, int M);
int main()
{
	int N, M;
	scanf("%d %d", &N, &M);
	Kruskal(N, M);
	
}

int* InitializeUnion(int N)
{
	int* a = (int*)malloc(sizeof(int) * (N+1));
	for (int i = 1; i <= N; i++)
	{
		a[i] = -1;
	}
	return a;
}
int FindRoot(int* a, int Item)
{
	int Root = Item;
	while (a[Root] > 0)
	{
		Root = a[Root];
	}
	return Root;
}
void Combine(int* a, int Root1, int Root2)
{
	if (a[Root1] < a[Root2])
	{
		a[Root1] += a[Root2];
		a[Root2] = Root1;
	}
	else
	{
		a[Root2] += a[Root1];
		a[Root1] = Root2;
	}

}
struct Edge* InitializeEdge(int M)
{
	struct Edge* EdgeSet = (struct Edge*)malloc(sizeof(struct Edge) * M);
	for (int i = 0; i < M; i++)
	{
		scanf("%d %d %d", &EdgeSet[i].Vertex1, &EdgeSet[i].Vertex2, &EdgeSet[i].Weight);
		EdgeSet[i].Flag = 0;
	}
	sort(EdgeSet, EdgeSet + M, EdgeRule());
	return EdgeSet;
}
int Kruskal(int N,int M)
{
	int* Union = InitializeUnion(N);
	struct Edge* EdgeSet = InitializeEdge(M);
	int EdgeNum = 0;
	int WeightSum = 0;
	int Root1, Root2;
	int SubSet=0;
	for (int i = 0; i < M; i++)
	{
		Root1 = FindRoot(Union, EdgeSet[i].Vertex1);
		Root2 = FindRoot(Union, EdgeSet[i].Vertex2);
		if (Root1 != Root2)
		{
			WeightSum += EdgeSet[i].Weight;
			Combine(Union, Root1, Root2);
			EdgeNum++;
		}
	}
	for (int i = 1; i <= N; i++)
	{
		if (Union[i] < 0)
		{
			SubSet++;
		}
	}
	if(SubSet>1)
	printf("%s\n%d","No MST",SubSet);
	else {
		int* Union2 = InitializeUnion(N);
		int Back = Work(N - 1, EdgeSet, Union2, 0, M);
		if (Back == 1)
		{
			printf("%d\n%s", WeightSum, "Yes");
		}
		else
		{
			printf("%d\n%s", WeightSum, "No");
		}
	}
	return EdgeNum;
}
int Work(int N, struct Edge* EdgeSet, int* Union, int th,int M)
{
	if (N == 0)
		return 1;
	else
	{
		int Root1, Root2,i,Root1Num,Root2Num,Root1C,Root2C,Root1A,Root2A;
		for (i = th; i < M; i++)
		{

				Root1 = FindRoot(Union, EdgeSet[i].Vertex1);
				Root2 = FindRoot(Union, EdgeSet[i].Vertex2);
				
				if (Root1 != Root2)
				{
					Root1Num = Union[Root1];
					Root2Num = Union[Root2];
					Combine(Union, Root1, Root2);
					Root1A = Union[Root1];
					Root2A = Union[Root2];
					EdgeSet[i].Flag = 1;
					int Back = Work(N - 1, EdgeSet, Union, i + 1, M);
					if (Back == -1)
						return -1;
					else {
						Union[Root1] = Root1Num;
						Union[Root2] = Root2Num;
						for (int j = i + 1; j < M; j++)
						{

							if (EdgeSet[j].Weight == EdgeSet[i].Weight && EdgeSet[j].Flag == 0)
							{
								Root1C = FindRoot(Union, EdgeSet[j].Vertex1);
								Root2C = FindRoot(Union, EdgeSet[j].Vertex2);
								if (Root1C != Root2C)
								{
									return -1;
								}
							}
							else if (EdgeSet[j].Weight > EdgeSet[i].Weight)
							{

								return 1;
							}
						}

						return 1;
					}
				}
			}
		}
	}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值