1. 程式人生 > >【洛谷P1547】Out of Hay【最小生成樹】

【洛谷P1547】Out of Hay【最小生成樹】

題目大意:

題目連結:https://www.luogu.org/problemnew/show/P1547
求一個圖中生成樹最長邊長度最小的最小生成樹的最長邊。


思路:

閒的無聊刷水題。
很明顯一個最小生成樹過去求最長邊就可以了。
然後打了一個 P r i m Prim


在這裡插入圖片描述
為什麼會這樣呢?
因為 P r i m Prim 求最小生成樹時是從一個點找最短邊到達其它點,每次找已知集合的最小邊去擴充套件。但是一個圖中可能會有多個最小生成樹, P
r i m Prim
可以求出其中一個最小生成樹,但是可能這棵最小生成樹中的最長邊比另一個最小生成樹的最長邊要長。但是我們要使得這個最長邊儘量短,所以 P r i
m Prim
演算法是不能完成此題的。
所以可以考慮採用 K r u s k a l Kruskal
K r u s k a l Kruskal 每次在圖中選擇一條長度最短的邊,且該邊連線兩個不同的集合。那麼 K r u s k a l Kruskal 演算法就保證了在求出最小生成樹的前提下,每次選擇的邊最短。那麼就保證了最小生成樹的 最長邊(即最後一次選擇的邊)是最短的。


程式碼:

#include <cstdio>
#include <algorithm>
using namespace std;

const int N=2100;
const int M=10100;
int n,m,sum,father[N];

struct node
{
	int x,y,s;
}map[M];

bool cmp(node x,node y)
{
	return x.s<y.s;
}

int find(int x)
{
	return x==father[x]?x:father[x]=find(father[x]);
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
		scanf("%d%d%d",&map[i].x,&map[i].y,&map[i].s);
	sort(map+1,map+1+m,cmp);  //排序
	for (int i=1;i<=n;i++)
		father[i]=i;
	for (int i=1;i<=m;i++)
	{
		if (find(map[i].x)!=find(map[i].y))  //兩個不同的集合
		{
			father[find(map[i].y)]=find(map[i].x);
			sum++;
		}
		if (sum==n-1)  //求出了最小生成樹
		{
			printf("%d\n",map[i].s);
			break;
		}
	}
	return 0;
}