1. 程式人生 > 其它 >P1547 Out of Hay 題解

P1547 Out of Hay 題解

P1547 Out of Hay 題解

Content

\(\text{Bessie}\)打算調查\(N\)個農場的乾草儲備情況,她將從1號農場出發,順著連線農場的\(M\)條邊調查,每條邊的長度為\(a_i\)\(\text{Bessie}\)想知道,這個農場的地圖中最小生成樹中最長邊的長度。

資料範圍:\(2\leqslant N\leqslant2000,1\leqslant M\leqslant10000,a_i\leqslant10^9\)

Solution

最小生成樹的模板題,剛學最小生成樹的新手可利用此題加強鞏固。

其實這道題目在\(POJ\)上有一模一樣的題,叫做\(\text{Highways(POJ2485)}\)。它們兩道題目都是讓你求無向圖中的最小生成樹中最長邊的長度。還有一個在洛谷上的

\(\text{P1111}\),實質上也和本題一樣。

很簡單,我們在\(\text{P3366}\)裡頭是不是讓你求最小生成樹的邊權和?還記得\(\text{Kruskal}\)版本的核心程式碼是什麼嗎?

for(int i = 1; i <= m; ++i) {
		int x = g(e[i].u), y = g(e[i].v);
		if(x != y) {
			f[x] = y;
			ans += e[i].w;
			cnt++;
		}
		if(cnt == n - 1)	break;
	}

那麼這道題目很簡單,就在這上面的\(\text{ans += e[i].w}\)

的地方改動一下。這裡是用的求和操作是不是?那麼就把它改成取\(\max\)操作就可以了。

就像這樣:

for(int i = 1; i <= m; ++i) {
		int x = g(e[i].u), y = g(e[i].v);
		if(x != y) {
			f[x] = y;
			ans = max(ans, e[i].w);	//這裡改動!
			cnt++;
		}
		if(cnt == n - 1)	break;
	}

把它改完,交上去,就過了!

是不是很簡單?

Code

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

int n, m, x, y, z, f[2000010], line, side, sum;
inline int read () {
	char ch = getchar();
	int x = 0, f = 1;
	while (ch < '0' || ch >'9') {
		if(ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9')
		x = x * 10 + (ch ^ 48), ch = getchar();
	return x * f;
}

struct Point {
	int u, v, w;
} po[2000010];

bool sorting_cmp(const Point &a,const Point &b) {
	return a.w < b.w;
}
 
inline int find(int x) {
	if(f[x] == 0)	return x;
	else			return f[x] = find(f[x]);
}

int main() {
	n = read(), m = read();
	for(int i = 1; i <= m; ++i) {
		x = read(), y = read(), z = read();
		po[line].u = x, po[line].v = y, po[line].w = z;
		line++;
	}
	sort(po, po + line, sorting_cmp);
	for(int i = 0; i < line; ++i) {
		int t = po[i].w,
		ufa = find(po[i].u), vfa = find(po[i].v);
		if(ufa != vfa) {
			sum = max(sum, t);
			f[ufa] = vfa;
			line++;
		}
		if(line == n - 1)	break;
	}
	cout << sum;
	return 0;
}