思路是对所有边枚举,每次以一条边与其他边作差跑最小生成树,O(m2logm)
#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;
}