codevs 1001 舒适的路线 (并查集)

题目描述 Description

Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。
Z小镇附近共有
N(1<N≤500)个景点(编号为1,2,3,…,N),这些景点被M(0<M≤5000)条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路。也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。频繁的改变速度使得游客们很不舒服,因此大家从一个景点前往另一个景点的时候,都希望选择行使过程中最大速度和最小速度的比尽可能小的路线,也就是所谓最舒适的路线。


输入描述 Input Description
第一行包含两个正整数,N和M。
接下来的M行每行包含三个正整数:x,y和v(1≤x,y≤N,0 最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。
 

输出描述 Output Description

如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。

样例输入 Sample Input

样例1
4 2
1 2 1
3 4 2
1 4

样例2
3 3
1 2 10
1 2 5
2 3 8
1 3

样例3
3 2
1 2 2
2 3 4
1 3

样例输出 Sample Output

样例1
IMPOSSIBLE

样例2
5/4

样例3
2

数据范围及提示 Data Size & Hint

N(1<N≤500)

M(0<M≤5000)

Vi在int范围内

简单的并查集

把边权按从小到大的顺序排好序枚举每一条边,把这条边的边权作为ans_max,接下来从这条边开始按顺序(从大到小)枚举每一条比它小的边,并且把这条边的两端点划分到一个联通块中,并且判断起点和终点是否在同一个联通块中,如果在同一个联通块中,那么当前枚举到的边的权值就是ans_min,然后更新当前最优解即可。

原理:枚举、贪心,因为我们要求ans_max与ans_min的最小比值,ans_max与ans_min越接近肯定是越好的。所以我们枚举ans_max,这样就可以把ans_max当成常数,那么ans_min的值一定是越大越好(当然,它不可能大过ans_max),所以我们从当前枚举到的边开始,每次加一条略小的边进入,当S与T第一次联通时,ans_min的值是最大的,那么就能保证他们的比值是当前ans_max下最小的。

时间复杂度:o(n^2logn)空间复杂度:o(n)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<stdlib.h>
 6 #include<cmath>
 7 using namespace std;
 8 #define inf 1<<30
 9 #define N 5006
10 ////////////并查集/////////////////
11 #define M 506
12 int fa[M];
13 void init(){
14     for(int i=0;i<M;i++){
15         fa[i]=i;
16     }
17 }
18 int find(int x){
19     return fa[x]==x?x:fa[x]=find(fa[x]);
20 }
21 void merge(int x,int y){
22     int root1=find(x);
23     int root2=find(y);
24     if(root1==root2){
25         return;
26     }
27     fa[x]=y;
28 }
29 ////////////并查集/////////////////
30 int n,m;
31 struct Node{
32     int a,b,v;
33 }node[N];
34 bool cmp(Node x,Node y){
35     return x.v<y.v;
36 }
37
38 int gcd(int x,int y){
39     return y==0?x:gcd(y,x%y);
40 }
41
42 int main()
43 {
44     while(scanf("%d%d",&n,&m)==2){
45         for(int i=0;i<m;i++) scanf("%d%d%d",&node[i].a,&node[i].b,&node[i].v);
46         sort(node,node+m,cmp);
47         int _max=inf;
48         int _min=1;
49         int st,ed;
50         scanf("%d%d",&st,&ed);
51         for(int i=0;i<m;i++){
52             init();
53             for(int j=i;j>=0;j--){
54                 merge(node[j].a,node[j].b);
55                 if(find(st)==find(ed)){
56                     if( (_max*1.0/_min) > (node[i].v*1.0/node[j].v) ){
57                         _max=node[i].v;
58                         _min=node[j].v;
59                         //printf("===%d %d\n",_max,_min);
60                     }
61                     break;
62                 }
63             }
64         }
65         //printf("---%d %d\n",_max,_min);
66         int r=gcd(_max,_min);
67         if(_max==inf && _min==1){
68             printf("IMPOSSIBLE\n");
69             continue;
70         }
71         _max/=r;
72         _min/=r;
73         if(_min==1){
74             printf("%d\n",_max);
75         }
76         else{
77             printf("%d/%d\n",_max/r,_min/r);
78         }
79
80     }
81     return 0;
82 }

时间: 2024-08-02 15:11:16

codevs 1001 舒适的路线 (并查集)的相关文章

求最大边/最小边的比值最小的路径 codevs 1001 舒适的路线

codevs 1001 舒适的路线 2006年 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光.Z小镇附近共有N(1<N≤500)个景点(编号为1,2,3,…,N),这些景点被M(0<M≤5000)条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路.也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车

codevs 1001 舒适的路线

我到底什么时候才能学会不看题解把题写出来.... 把所有的边从小到大排序,for一遍把当前边作为最大值,然后倒着for,更新答案即可.若不能更新答案则有IMPOSSIBLE. 这是连续第二道没做出来的并查集了. 某神犇说用spfa比较快...没验证过,也不想验证. #include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define

枚举+并查集 之 CODE[VS] 1001 舒适的路线 2006年

/* 枚举所有情况,通过并查集判断在当前情况下,是否包含起始和终止点, 若包含,则需判断是否在当前情况下,最大速度和最小速度的比更小, 若是,则更新最大速度和最小速度. 最后枚举过所有情况后,即获得答案. */ 1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstddef> 5 #include <iterator> 6 #include &l

1001 舒适的路线

题目描述 Description Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光.Z小镇附近共有N(1<N≤500)个景点(编号为1,2,3,…,N),这些景点被M(0<M≤5000)条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路.也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi.频繁的改变速度使得游客们很不舒服,因此大家从一个景点前往另一个景点的时候,都希望选择行使过程中最大速度和最小速度的比尽

codevs 1001 舒适的线路 kruskal/gcd

舒适的线路 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://www.codevs.cn/problem/1001/ Description Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光. Z小镇附近共有N(1<N≤500)个景点(编号为 1,2,3,…,N),这些景点被M(0<M≤5000)条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路.也许是为了保护该地的旅 游资源,Z小镇有个奇怪的规定,就是对于一条给定的

codevs 3372 选学霸(hash+并查集+多重背包)

先通过并查集处理出来有多少种不同的集合,每个集合有多少人.一定要不要忘记了与别的没有联系的独立点. 并查集的时候可以通过hash处理出来每个数目相同的集合的个数. 这样以人数为权值,个数为限制进行多重背包,结果就是答案. 题目链接:http://codevs.cn/problem/3372/ #include <algorithm> #include <iostream> #include <stdlib.h> #include <string.h> #in

舒适的旅行(并查集)

1050: [HAOI2006]旅行comf Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3107  Solved: 1701[Submit][Status][Discuss] Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小.如果S和T之间没有路径,输出”IMPOSSIBLE”,否则

nyoj 711最舒适的路线(第六届河南省程序设计大赛 并查集)

最舒适的路线 时间限制:5000 ms  |  内存限制:65535 KB 难度:5 描述 异形卵潜伏在某区域的一个神经网络中.其网络共有N个神经元(编号为1,2,3,-,N),这些神经元由M条通道连接着.两个神经元之间可能有多条通道.异形卵可以在这些通道上来回游动,但在神经网络中任一条通道的游动速度必须是一定的.当然异形卵不希望从一条通道游动到另一条通道速度变化太大,否则它会很不舒服. 现在异形卵聚居在神经元S点,想游动到神经元T点.它希望选择一条游动过程中通道最大速度与最小速度比尽可能小的路

CODEVS1001 舒适的路线 (并查集)

对所有边从大到小排序,枚举最大边,O(m)验证,用并查集维护图是否联通. program CODEVS1001; const maxm=5008; maxn=508; INF=2000000000; type arr=record u,v,w:int64; end; var eg:array[0..maxm] of arr; fa:array[0..maxn] of longint; i,j,m,n,x,y,z,s,t,u,v,d:longint; ans1,ans2:int64; proced