Loading

201812-4 数据中心

时间限制:1.0s
内存限制:512MB
题目描述:
image

分析

我们可以发现,Tmax的最小值就是图的最小生成树的最大边,因此可以选择Prim算法或者Kruskal算法。而Kruskal算法会对边进行排序,更便于我们找到最大边,因此选择Kruskal算法。步骤如下:

  1. 对边进行排序
  2. 加入边时判断是否构成环(并查集

解法

首先选择数据结构存储输入数据,输入数据主要是边的信息,数据结构如下:

struct Edge
{
	unsigned int u, v;
	long t;
	bool operator < (const Edge& a)const
	{
		return t < a.t;
	}
}e[MAXM];
Edge e[MAXM];//用数组存储边

接着定义并查集存储图的连通性:

//并查集初始化,每个节点的父节点都是自己
void init(unsigned int n)
{
	unsigned int i;
	for (i = 0; i < n; i++)
	{
		f[i] = i;
	}
}

//查找根节点并返回,途中进行路径压缩
unsigned int find(unsigned int i)
{
	unsigned int tmp = i;
	while (f[tmp] != tmp)//找到根节点为tmp
	{
		tmp = f[tmp];
	}
	while (i != tmp)//从i到根节点的路上,每个结点都让其指向根节点
	{
		unsigned int k = i;
		i = f[i];
		f[k] = tmp;
	}
	return tmp;
}

//合并两个集合,并且返回是否可以合并的判断
bool join(unsigned int a, unsigned int b)
{
	unsigned int fa = find(a);
	unsigned int fb = find(b);
	if (fa != fb)
	{
		f[fb] = fa;//注意是根节点合并
		return true;
	}
	return false;
}

Kruskal算法实现:

for (unsigned int i = 0; i < m; i++)
{
    unsigned int a, b;
    a = e[i].v;
    b = e[i].u;
    if (join(a, b))//如果可以合并则不会构成环
    {
        count++;
        ans = e[i].t;
        if (count == n - 1)//添加n-1条边后即构成最小生成树
       		break;
    }
}

完整代码

posted @ 2021-08-03 19:40  Imane219  阅读(49)  评论(0)    收藏  举报
hi