题目链接:http://wikioi.com/problem/1001/
算法与思路:并查集,首先枚举速度最大的那条边,然后把速度大于这条边的边都删掉,
接下来的任务就是在残图中寻找一条路,路上的最小的那条边要尽量大。
这个地方用并查集实现,对于剩下的边由大到小排序,
然后逐个往集合里面加,直到某次加入操作后起点和终点被加到了同一个集合,
这时停止操作,最后加的那条边就是一条所求的最小边最大的。算法复杂度O(m^2)。
代码实现:
#include <stdio.h> #include <stdlib.h> #include <algorithm> #define INF 0xffffff using namespace std; int set[505]; int n, m, s, t, k; int Max, Min; struct node { int x; int y; int v; }edge[5005]; bool cmp(node a, node b) { return a.v < b.v; } int find(int x) { return x == set[x] ? x : set[x] = find(set[x]); } int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } int main() { double ans = INF; scanf("%d %d",&n, &m); for(int i = 1; i <= m; ++i) scanf("%d %d %d", &edge[i].x, &edge[i].y, &edge[i].v); scanf("%d %d", &s, &t); sort(edge + 1, edge + m + 1, cmp); for(int i = 1; i <= m; ++i) { for(int j = 1; j <= n; ++j) set[j] = j; for(k = i; k <= m; ++k) { if(find(edge[k].x) != find(edge[k].y)) set[set[edge[k].x]] = set[edge[k].y]; if(find(s) == find(t)) { if(edge[k].v / 1.0 / edge[i].v < ans) { Max = edge[k].v; Min = edge[i].v; ans = edge[k].v / 1.0 / edge[i].v; } break; } } } if(ans == INF) printf("IMPOSSIBLE\n"); else { int temp = gcd(Max, Min); Max /= temp; Min /= temp; printf("%d",Max); if(Min != 1) printf("/%d",Min); printf("\n"); } return 0; }