题目链接: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;
}