zoukankan      html  css  js  c++  java
  • 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
    ",_max,_min);
    60                     }
    61                     break;
    62                 }
    63             }
    64         }
    65         //printf("---%d %d
    ",_max,_min);
    66         int r=gcd(_max,_min);
    67         if(_max==inf && _min==1){
    68             printf("IMPOSSIBLE
    ");
    69             continue;
    70         }
    71         _max/=r;
    72         _min/=r;
    73         if(_min==1){
    74             printf("%d
    ",_max);
    75         }
    76         else{
    77             printf("%d/%d
    ",_max/r,_min/r);
    78         }
    79 
    80     }
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    Java学习笔记-Lambda表达式
    Java学习笔记-枚举类
    Java学习笔记-枚举类
    Java学习笔记-包装类
    js 递归 汉诺塔的例子
    js 用 hasOwnProperty() 判定属性是来自该对象成员,还是原型链
    正则,js函数math()提取混乱字符串中多个字符串内容
    封装好的cookie的三个常用函数 cookie的添加、删除、提取操作函数
    解决ie6下png背景不能透明bug
    ie6下标签定义的高失效,显示的高不受设定的height值影响
  • 原文地址:https://www.cnblogs.com/UniqueColor/p/4786941.html
Copyright © 2011-2022 走看看