kruskal求调
查看原帖
kruskal求调
481621
Zhang_Wenjie楼主2024/4/8 13:47

思路是对所有边枚举,每次以一条边与其他边作差跑最小生成树,O(m2log⁡m)O(m^2\log m)

#include <bits/stdc++.h>
#define re register int 
#define min(x, y) (x < y ? x : y)
#define max(x, y) (x > y ? x : y)
using namespace std;
const int N = 510, M = 5e3 + 10, inf = 1e6;
struct edge
{
	int x, y, w, cha;
}e[M];
int top, fa[N];
int n, m, s, t, minw, maxw, mn, mx, cha = inf;
bool cmp(edge i, edge j) { return i.cha < j.cha; }

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

inline void kruskal(int k)
{
	for (re i = 1; i <= n; i ++) fa[i] = i;
	for (re i = 1; i<= m; i ++)
		e[i].cha = abs(k - e[i].w);
	sort(e + 1, e + m + 1, cmp);
	
	for (re i = 1; i <= m; i ++)
	{
		int x = e[i].x, y = e[i].y, w = e[i].w;
		if (find(x) != find(y))
		{
			fa[find(x)] = find(y);
			minw = min(minw, w);
			maxw = max(maxw, w);
		}
	}
	return;
}

inline void print(int a, int b)
{
	int c = max(a, b), n = 1;
	for (re i = c; i; i --)
	{
		if (a % i == 0 && b % i == 0)
		{
			a /= i;
			b /= i;
//			n *= i; 最大公约数 
		}
	}
	cout << a << '/' << b << '\n';
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n >> m;
	for (re i = 1; i <= m; i ++)
	{
		int x, y, w; cin >> x >> y >> w;
		e[i] = {x, y, w, 0};
	}
	cin >> s >> t;
	
	bool check = false;
	for (re i = 1; i <= m; i ++)
	{
		int k = e[i].w;
		minw = inf, maxw = 0;
		kruskal(k);
		if (find(s) == find(t)) check = true;
		if (abs(minw - maxw) < cha)
		{
			cha = abs(minw - maxw);
			mn = minw, mx = maxw;
		}
	}
	if (!check) { cout << "IMPOSSIBLE\n"; return 0; }
	if (mx % mn != 0) print(mx, mn);
	else cout << mx / mn << '\n';
	
	return 0;
	
}
2024/4/8 13:47
加载中...