[HAOI2006]旅行 题解(kruskal)

[HAOI2006]旅行

Description

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”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。

Solution

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

struct rode{
    int x,y,w;
}r[10010];
int n,m,i,j,k,s,t,f[1010]; 

inline int rd(){
    int x=0;
    bool f=1;
    char c=getchar();
    while(!isdigit(c)){
        if(c==‘-‘) f=0;
        c=getchar();
    }
    while(isdigit(c)){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return f?x:-x;
}

int gcd(int a,int b){return b?gcd(b,a%b):a;}

int find(int x){
    if(x==f[x])return x;
    return f[x]=find(f[x]);
}

void merge(int x,int y){
    f[find(x)]=find(y);
}

bool judge(int x,int y){
    if(find(x)==find(y))return true;
    return false;
}

bool cmp(rode x,rode y){
    return x.w<y.w;
}

int main(){
    int nowmin=1,nowmax=0x7f7f7f7f;
    double ans=2147483647;
    n=rd();
    m=rd();
    for(i=1;i<=m;++i){
        r[i].x=rd();
        r[i].y=rd();
        r[i].w=rd();
    }
    s=rd();
    t=rd();
    sort(r+1,r+1+m,cmp);
    for(j=1;j<=m;++j){
        bool flag=0;
        int minn;
        for(i=1;i<=n;++i)f[i]=i;
        for(i=j;i<=m;++i){
            if(!judge(r[i].x,r[i].y))merge(r[i].x,r[i].y);
            if(judge(s,t))break;
        }
        if(judge(s,t)){
            if((double)((double)r[i].w/(double)r[j].w)<(double)((double)nowmax/(double)nowmin)){
                nowmin=r[j].w;
                nowmax=r[i].w;
            }
        }
    }
    if(nowmax==0x7f7f7f7f)printf("IMPOSSIBLE\n");
    else{
        int temp=gcd(nowmin,nowmax);
        if(temp==nowmin) printf("%d\n",nowmax/nowmin);
        else printf("%d/%d",nowmax/temp,nowmin/temp);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/COLIN-LIGHTNING/p/8684011.html

时间: 2024-07-30 09:03:06

[HAOI2006]旅行 题解(kruskal)的相关文章

[BZOJ1050] [HAOI2006] 旅行comf (Kruskal, LCT)

Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小.如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需要,表示成一个既约分数. 备注: 两个顶点之间可能有多条路径. Input 第一行包含两个正整数,N和M.下来的M行每行包含三个正整数:x,y和v.表示景点x到景点y之间有一条双向公路,车辆必须以速度v在该公路

1050: [HAOI2006]旅行comf

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

bzoj 1050: [HAOI2006]旅行comf(最小生成树+并查集)

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

P2502 [HAOI2006]旅行 - 最小生成树【最小比值生成树(雾】

P2502 [HAOI2006]旅行 Sol: 暴力 枚举所有从S到T的路径,然后用maxw/minw更新答案. 时间复杂度:\(O(玄学)\) 正解 观察到边数\(m\leq5000\) 考虑由直接求maxw和minw -> 枚举minw求maxw 由于从S到T的路径上的最大值最小的边一定在最小生成树上(最小生成树的瓶颈路性质),所以我们可以将边从小到大排序,每次枚举边\(e_i\),并将剩下的\(e_i,e_{i+1}\dots e_m\)建最小生成树,当边\(e_k\)使S和T第一次连通时

[HAOI2006]旅行comf

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

BZOJ 1050: [HAOI2006]旅行comf(枚举+并查集)

[HAOI2006]旅行comf Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小.如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需要,表示成一个既约分数. 备注: 两个顶点之间可能有多条路径. Input 第一行包含两个正整数,N和M.下来的M行每行包含三个正整数:x,y和v.表示景点x到景点y之间有一条

luogu题解P2502[HAOI2006]旅行--最小生成树变式

题目链接 https://www.luogu.org/problemnew/show/P2502 分析 一个很\(naive\)的做法是从\(s\)到\(t\)双向BFS这当然会TLE 这时我就有个想法就是二分套二分边下标来求得一个比值,同时排序后从小到大枚举每一条边作为最小值,同时再枚举每一条边,如果边权之比小于比值就连起来用并查集维护连通性,可是这个时间复杂度\(O(m^2 log^2m \ \alpha(n))\)过不去QAQ 然后想为什么不直接枚举每条边作为最小值,同时搞一颗以这条边为最

BZOJ1050 [HAOI2006]旅行comf

Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T ,求一条路径,使得路径上最大边和最小边的比值最小.如果S和T之间没有路径,输出"IMPOSSIBLE",否则输出 这个比值,如果需要,表示成一个既约分数. 备注: 两个顶点之间可能有多条路径. Input 第一行包含两个正整数,N和M.下来的M行每行包含三个正整数:x,y和v.表示景点x到景点y之间有一条双向 公路

BZOJ [HAOI2006]旅行comf

题解:枚举最大边,然后对<=最大边的边做最大生成树,使最小边最大 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100009; const int oo=1000000000; int Gcd(int a,int b){ if(b==0)return a; return Gcd(b