【Luogu P2502】[HAOI2006]旅行
题目大意:
给定一个有 \(n\) 个点的无向图,求出从 \(s\) 到 \(t\) 的最短路上的最大权值与最小权值的比。
正文:
并查集查询 \(s\) 与 \(t\) 是否连通,可以通过给邻接表按权值从大到小排序,枚举每次连通的最大最小权值比即可。
代码:
int find_(int x) {if(x == fa[x])return x;return fa[x] = find_(fa[x]);}
void Add(int u, int v, int w)
{
e[++tot] = (node){u, v, head[u], w}, head[u] = tot;
}
bool cmp(node a, node b)
{
return a.w > b.w;
}
int gcd(int a, int b)
{
if(b == 0) return a;
return gcd(b, a%b);
}
int main()
{
scanf ("%d%d", &n, &m);
for (int i = 1; i <= n; i++) fa[i] = i;
for (int i = 1; i <= m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
Add(u, v, w);
fa[find_(u)] = find_(v);
}
scanf ("%d%d", &s, &t);
if(find_(s) != find_(t))
{
puts("IMPOSSIBLE");
return 0;
}
sort (e + 1, e + 1 + tot, cmp);
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++) fa[j] = j;
for (int j = i; j <= m; j++)
{
int u = e[j].from, v = e[j].to;
fa[find_(u)] = find_(v);
if(find_(s) == find_(t))
{
double opt = e[i].w * 1.0 / e[j].w * 1.0;
if(opt < ans)
maxsp = e[i].w, minsp = e[j].w, ans = opt;
break;
}
}
}
if(maxsp % minsp) printf("%d/%d", maxsp / gcd(maxsp, minsp), minsp / gcd(maxsp, minsp));
else printf("%d", maxsp / minsp);
return 0;
}