BZOJ 1050 旅行comf

题目如下:

题目描述

给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。

输入

第一行包含两个正整数,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
【样例输入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

样例输出

【样例输出1】
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2

用结构体存边:E[  ].fr(起始点)  E[  ].to(指向点)  E[  ].cost(权值)

此题用的是并查集来做的。首先对所有的边进行从小到大排序,定义ans1=inf为当前寻找到的最大边的最小值,ans2=1位当前的最小边。然后从小到大进行枚举(循环一:for(i=1;i<=m;i++))在循环一中建立以点为关键字的并查集数组。再进行第二重循环(for(int j=i;j<=n;j++)),该循环是从循环一进行到的边的编号开始,到最大的边,每添加一条边,将其开头和结尾添加在并查集中,再检测S和T的连通性即(if(find(S)==find(T)){ }),若联通则比较ans1/ans2与E[ j ].cost/E[ i ].cost的大小比较过程中可以交叉相乘,这样可以避免整除的问题。若新的比值更小则更新ans1和ans2的值并跳出循环二。若不连通依然比较ans1/ans2与E[ j ].cost/E[ i ].cost的大小,若新的比值小于原存的比值,则跳出循环二,因为循环二中E[j].cost是不断增大的。循环一结束后,主体就结束了,最后的输出一看就懂。

#include<iostream>

#include

<cstdio>

#include

<algorithm>#define inf 10000000

using namespace std;
struct edge{
    int fr,to,cost;
};
edge E[5001];
inline int comp(edge a,edge b)
{
    return a.cost<b.cost;
}
int m,n,s,t;
int fa[501];
inline int find(int x)
{
    if(fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}
inline int gcd(int a,int b)//a>b
{
    if(b==0) return a;
    return gcd(b,a%b);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    scanf("%d%d%d",&E[i].fr,&E[i].to,&E[i].cost);
    scanf("%d%d",&s,&t);
    sort(E+1,E+m+1,comp);
    int ans1=inf,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 f1=find(E[j].fr),f2=find(E[j].to);
            fa[f1]=f2;
            if(find(s)==find(t)){
                if(E[i].cost*ans1>E[j].cost*ans2)
                ans1=E[j].cost,ans2=E[i].cost;
                break;
            }
            if(E[i].cost*ans1<E[j].cost*ans2) break;
        }
    }
    int zdg=gcd(ans1,ans2);
    if(ans1==inf) printf("IMPOSSIBLE");
     else if(ans2!=zdg) printf("%d/%d",ans1/zdg,ans2/zdg);
      else printf("%d",ans1/ans2);
}
时间: 2024-10-09 00:44:45

BZOJ 1050 旅行comf的相关文章

BZOJ 1050 旅行comf(枚举最小边-并查集)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1050 题意:给出一个带权图.求一条s到t的路径使得这条路径上最大最小边的比值最小? 思路:将边排序.枚举最小边,然后将边一个一个插到并查集里,s和t联通时计算更新答案. struct node { int u,v,w; void get() { RD(u,v,w); } }; int cmp(node a,node b) { return a.w<b.w; } int n,m,s,t;

[BZOJ]1050 旅行comf(HAOI2006)

图论一直是小C的弱项,相比其它题型,图论的花样通常会更多一点,套路也更难捉摸. Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小.如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需要,表示成一个既约分数. 备注: 两个顶点之间可能有多条路径. Input 第一行包含两个正整数,N和M.下来的M行每行包含三个正

BZOJ 1050 旅行

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在该公

BZOJ 1050 旅行(并查集)

很好的一道题. 首先注意,要使的s到t的路径上最大边/最小边的值最小.我们可以尝试一下二分并验证答案. 但是不能二分最大边/最小边. 我们可以二分 最小边的权值.于是算法就出来了. 首先把边权排序.然后枚举最小的边,再依次添加不小于该边的边,直到s和t联通.用并查集维护即可. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include &l

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

【BZOJ】【1050】【HAOI2006】旅行comf

枚举/暴力/Kruskal orz……我sb了……其实是sb题<_< 有一道题问的是最小极差生成树……(不记得是什么名字了,就是求最大边权与最小边权差最小的生成树)做法是枚举最小边,然后kruskal找最大边 这题同理,因为$m\leq 5000$,所以$m^2$的算法即可…… 1 /************************************************************** 2 Problem: 1050 3 User: Tunix 4 Language: C

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

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之间有一条

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”,否则输出这个比值,如果需