[HAOI2006]旅行

Description

BZOJ1050

Luogu2502

Solution

做过我还不会……

就是枚举最小边然后跑MST。

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

typedef long long LL;
const int N = 500 + 10;
const int M = 5000+10;

struct Edge { 
	int u, v, w; 
	Edge(int u=0, int v=0, int w=0) : u(u), v(v), w(w) {}
} e[M];
int n, m, s, t;
int fa[N];
int mx, mn, ax, an;

int find(int x) {
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}
int merge(int x, int y) {
	int fx = find(x), fy = find(y);
	if (fx == fy) return 0;
	else {
		fa[fx] = fy;
		return 1;
	}
}

inline bool cmp(const Edge& x, const Edge &y) {
	return x.w < y.w;
}

int gcd(int x, int y) {
	return !y ? x : gcd(y, x%y);
}

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1, x, y, z; i <= m; ++i) {
		scanf("%d%d%d", &x, &y, &z);
		e[i] = Edge(x, y, z);
	}
	std::sort(e+1, e+m+1, cmp);
	scanf("%d%d", &s, &t);
	for (int i = m; i; --i) {
		mx = 0; mn = 0x3f3f3f3f;
		for (int j = 1; j <= n; ++j) fa[j] = j;
		// merge(u[i], v[i]);
		for (int j = i; j; --j) {
			if (merge(e[j].u, e[j].v)) {
				mx = std::max(mx, e[j].w);
				mn = std::min(mn, e[j].w);
				if (find(s) == find(t)) break;
			}
		}
		if (find(s) != find(t)) break;
		// printf("%d %d
", mx, mn);
		if (!ax) ax = mx, an = mn;
		else if ((double)mx / mn < (double)ax / an) ax = mx, an = mn;
	}
	if (ax == 0) puts("IMPOSSIBLE");
	else {
		if (ax % an == 0) printf("%d
", ax / an);
		else {
			int g = gcd(ax, an);
			printf("%d/%d
", ax / g, an / g);
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/wyxwyx/p/bzoj1050.html