[并查集]HAOI2006 旅行
2017-12-15 20:55
337 查看
题目描述
Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。Z小镇附近共有N个景点(编号为1,2,3,…,N),这些景点被M条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路。也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。速度变化太快使得游客们很不舒服,因此从一个景点前往另一个景点的时候,大家都希望选择行使过程中最大速度和最小速度的比尽可能小的路线,也就是所谓最舒适的路线。
Input
第一行包含两个正整数,N和M。
接下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路,车辆必须以速度v在该公路上行驶。
最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。
Output
如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。
1<N<=500
1<=x,y<=N,0<v<30000,x≠y
0<M<=5000
分析
这题看了一下,数据不大,可以m^2枚举。
但是如何判断是最大最小比呢?我想到了排序
排序以后,就很容易了,可是还有一个问题,如果要查找是否合并的话,要一个m^2的邻接矩阵,肯定MLE的
并查集可解此问题。
1、排序(由小到大)
2、每次枚举一个景点,当并查集发现起点与终点已经连接以后,退出第二层枚举(或者所有点都枚举一遍仍无法连接可以退出)
3、把最大值和最小值的比值与原最大值和最小值的比值对比,更新
4、欧几里德约分即可
(温馨提示,比值等式列为a:b=c:d,为求精确度我转化为乘法ad=bc)
Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。Z小镇附近共有N个景点(编号为1,2,3,…,N),这些景点被M条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路。也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。速度变化太快使得游客们很不舒服,因此从一个景点前往另一个景点的时候,大家都希望选择行使过程中最大速度和最小速度的比尽可能小的路线,也就是所谓最舒适的路线。
Input
第一行包含两个正整数,N和M。
接下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路,车辆必须以速度v在该公路上行驶。
最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。
Output
如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。
1<N<=500
1<=x,y<=N,0<v<30000,x≠y
0<M<=5000
分析
这题看了一下,数据不大,可以m^2枚举。
但是如何判断是最大最小比呢?我想到了排序
排序以后,就很容易了,可是还有一个问题,如果要查找是否合并的话,要一个m^2的邻接矩阵,肯定MLE的
并查集可解此问题。
1、排序(由小到大)
2、每次枚举一个景点,当并查集发现起点与终点已经连接以后,退出第二层枚举(或者所有点都枚举一遍仍无法连接可以退出)
3、把最大值和最小值的比值与原最大值和最小值的比值对比,更新
4、欧几里德约分即可
(温馨提示,比值等式列为a:b=c:d,为求精确度我转化为乘法ad=bc)
#include <iostream> #include <cstdio> using namespace std; int n,m,a[5001][3],i,j,f[501],mx,mn,s,t; void qs(int l,int h) { int i=l,j=h,mid=a[(l+h)/2][2],t; if (l>=h) return; do { while (a[i][2]<mid) i++; while (a[j][2]>mid) j--; if (i<=j) { t=a[i][0];a[i][0]=a[j][0];a[j][0]=t; t=a[i][1];a[i][1]=a[j][1];a[j][1]=t; t=a[i][2];a[i][2]=a[j][2];a[j][2]=t; i++;j--; } } while (i<=j); qs(i,h); qs(l,j); } int fin(int x) { int i=x,root; while (f[i]!=i) i=f[i]; root=i; i=x; while (f[i]!=i) { f[i]=root; i=f[i]; } return root; } void uni(int x,int y) { int i=fin(x),j=fin(y); f[i]=f[j]; } int gcd(int a,int b) { if (b==0) return a; return gcd(b,a%b); } int main() { scanf("%d%d",&n,&m); for (i=1;i<=m;i++) scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]); scanf("%d%d",&s,&t); qs(1,m); mx=5000;mn=1; for (i=1;i<=m;i++) { for (j=1;j<=n;j++) f[j]=j; j=i-1; while (j<=m&&fin(s)!=fin(t)) { j++; uni(a[j][0],a[j][1]); } if (fin(s)!=fin(t)) break; if (a[j][2]*mn<a[i][2]*mx) { mx=a[j][2]; mn=a[i][2]; } } if (mx==5000) { printf("IMPOSSIBLE"); return 0; } int q=gcd(mx,mn); mx/=q;mn/=q; if (mx%mn==0) printf("%d",mx/mn); else printf("%d/%d",mx,mn); }
相关文章推荐
- 【bzoj1050】[HAOI2006]旅行comf 并查集
- 【穷举+并查集】BZOJ1050(HAOI2006)[旅行comf]题解
- 【并查集】BZOJ1050 [HAOI2006]旅行comp
- [并查集]BZOJ 1050——[HAOI2006]旅行comf
- bzoj 1050: [HAOI2006]旅行comf 并查集
- BZOJ 1050: [HAOI2006]旅行comf 贪心,并查集
- bzoj1050 [HAOI2006]旅行comf(并查集)
- bzoj 1050: [HAOI2006]旅行comf(最小生成树+并查集)
- [BZOJ1050][HAOI2006]旅行comf(并查集)
- bzoj 1050: [HAOI2006]旅行comf 并查集
- BZOJ 1050: [HAOI2006]旅行comf (并查集 或 单调队列)
- [BZOJ1050][HAOI2006]旅行comf(并查集)
- ssl1312Z&P2502-[HAOI2006]旅行【图论,并查集】
- BZOJ1050(HAOI2006)[旅行comf]--并查集
- 【BZOJ】1050: [HAOI2006]旅行comf(暴力+并查集)
- bzoj 1050: [HAOI2006]旅行comf【枚举+并查集】
- BZOJ 1050 [HAOI2006]旅行comf CODEVS 1001 舒适的路线 并查集
- BZOJ 1050: [HAOI2006]旅行comf( 并查集 )
- 【BZOJ】1050 [HAOI2006]旅行comf 并查集
- BZOJ 1050: [HAOI2006]旅行comf 并查集