[BZOJ1050][HAOI2006]旅行
题目描述
Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。Z小镇附近共有N个景点(编号为1,2,3,…,N),这些景点被M条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路。也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。速度变化太快使得游客们很不舒服,因此从一个景点前往另一个景点的时候,大家都希望选择行使过程中最大速度和最小速度的比尽可能小的路线,也就是所谓最舒适的路线。
输入输出格式
输入格式:第一行包含两个正整数,N和M。
接下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路,车辆必须以速度v在该公路上行驶。
最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。
输出格式:如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。
输入输出样例
输入样例#1:
4 2 1 2 1 3 4 2 1 4
输出样例#1:
IMPOSSIBLE
输入样例#2:
3 3 1 2 10 1 2 5 2 3 8 1 3
输出样例#2:
5/4
输入样例#3:
3 2 1 2 2 2 3 4 1 3
输出样例#3:
2
说明
【数据范围】
1<N≤500
1≤x,y≤N,0<v<30000,x≠y
0<M≤5000
一看这种题满脑子都是并查集,貌似好像貌似...被洗脑了?
我们先按边权从小到大排序,然后枚举最小的路径是哪个,之后合并集合,一旦发现s, t在一个集合,就把当前路径的边权除以枚举最小路径的边权来更新答案。
于是乎...做完了。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; inline int read(){ int res=0;char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();} return res; } int n, m, s, t; struct edge{ int x, y, val; }ed[10005]; inline bool cmp(edge a, edge b){return a.val < b.val;} int fa[505]; int Find(int x){return x==fa[x]?x:fa[x]=Find(fa[x]);} int ans1, ans2, res1, res2; int gcd(int x, int y){return y==0?x:gcd(y, x%y);} int main() { n = read(), m = read(); for (int i = 1 ; i <= m ; i ++) { int x = read(), y = read(), z = read(); ed[i] = (edge){x, y, z}; } s = read(), t = read(); sort(ed + 1, ed + 1 + m, cmp); ans1 = 1e9; ans2 = 1; 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 x = ed[j].x, y = ed[j].y; int fx = Find(x), fy = Find(y); if (fx == fy) continue; fa[fx] = fy; int fs = Find(s), ft = Find(t); if (fs == ft) { res1 = ed[j].val, res2 = ed[i].val; break; } } if ((double)((double)ans1 / (double)ans2) >= (double)((double)res1 / (double)res2)) ans1 = res1, ans2 = res2; } if (ans1 == 1e9 and ans2 == 1) return puts("IMPOSSIBLE"), 0; if (ans1 % ans2 == 0) return printf("%d\n", ans1/ans2), 0; int g = gcd(ans1, ans2); return printf("%d/%d", ans1/g, ans2/g), 0; }