poj3522-kruscal算法求最小生成树+枚举

题意;

给你一个无向,求所有生成树中,最大边与最小边差值最小的那个值。

算法分析:

排序,从最小边开始,枚举每一条最小边,然后求最小生成树,求差值,然后求出最小值。

代码;

#include 
#include 
#include 

#define nMax 105
#define inf 0x7fffffff
struct EDGE
{
	int u,v,w;
}edge[nMax * nMax / 2];

int cmp(const void *a, const void *b)//排序
{
	struct EDGE *c = (struct EDGE *)a;
	struct EDGE *d = (struct EDGE *)b;
	return c->w - d->w;
}
int n,m;
int father[nMax],rank[nMax];
void init()//并查集初始化
{
	for (int i = 1; i <= n; ++ i)
	{
		father[i] = i;
		rank[i] = 0;
	}
}
int find(int x)//并查集找父节点
{
	if (x != father[x])
	{
		father[x] = find(father[x]);
	}
	return father[x];
}
void unions(int x, int y)//并查集合并
{
	x = find(x);
	y = find(y);
	if (rank[x] > rank[y])
	{
		father[y] = x;
	}
	else
	{
		father[x] = y;
		if (rank[x] == rank[y])
		{
			rank[y] ++;
		}
	}
}
int main()
{
	while (scanf("%d %d", &n, &m) && n)
	{
		for (int i = 0; i < m; ++ i)
		{
			scanf("%d %d %d", &edge[i].u, &edge[i].v, &edge[i].w);
		}
		qsort(edge, m, sizeof(edge[0]), cmp);
		int ans = inf;
		for (int i = 0; i < m - n + 2; ++ i)//枚举每一条最小边,由于生成树最少要n-1条边,这里i后面至少要保证有n-1条边
		{
			init();
			int num = 0;
			for (int j = i; j < m; ++ j)//对于每一条最小边,在此基础上求最小生成树,求差值
			{
				if (find(edge[j].u) != find(edge[j].v))
				{
					unions(edge[j].u, edge[j].v);
					num ++;
					if (num == n - 1)//如果已经n-1条边了,证明已经n个点了,不用再求了,已经找到最小生成树了,直接break,同时更新最小值
					{
						if (ans > edge[j].w - edge[i].w)
						{
							ans = edge[j].w - edge[i].w;
						}
						break;
					}
				}
			}
		}
		if (ans != inf)
		{
			printf("%d\n", ans);
		}
		else
			printf("-1\n");
	}
	return 0;
}


 

 

 

你可能感兴趣的:(枚举,图论)