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之间有一条双向
公路,车辆必须以速度v在该公路上行驶。最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速
度比最小的路径。s和t不可能相同。
1<N<=500,1<=x,y<=N,0<v<30000,0<M<=5000

Output

  如果景点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

题解:

贪心+并查集+最小生成树

对于求最小比的做法,即让分子分母最接近即可

实现方法:

主要思想:kruskal

0.预处理:按边权升序排序

1.不断把最小速度提前。

2.查看当前最小速度是否符合题意,即s和t联通,用kruskal算法

3.更新最优解

1704857 ksq2013 1050 Accepted 884 kb 408 ms C++/Edit 1354 B 2016-11-14 11:08:05
#include<cstdio>
#include<algorithm>
using namespace std;
inline void F(int &x){
    x=0;int c=getchar(),f=1;
    for(;c<48||c>57;c=getchar())
        if(!(c^45))
            f=-1;
    for(;c>47&&c<58;c=getchar())
        x=(x<<1)+(x<<3)+c-48;
    x*=f;
}
inline int gcd(int x,int y,int t=0){
    for(;y;)
        t=x%y,
        x=y,
        y=t;
    return x;
}
int n,m,f[501],mx=0x3f3f3f3f,mn=1,s,t;
inline int bin(int x){
    int p1,p2=x;
    for(;f[x]^x;x=f[x])
        ;
    for(;f[p2]^p2;)
        p1=f[p2],
        f[p2]=x,
        p2=p1;
    return x;
}
struct edge{
    int u,v,w;
    bool operator<(const edge h)const{
        return w<h.w;
    }
}e[5001];
int main(){
    F(n),F(m);
    for(int i=1;i<=m;i++)
        F(e[i].u),
        F(e[i].v),
        F(e[i].w);
    sort(e+1,e+1+m);
    F(s),F(t);
    for(int k=1,i;k<=m;k++){
        for(i=1;i<=n;i++)
            f[i]=i;
        for(i=k;i<=m;i++){
            int u=bin(e[i].u);
            int v=bin(e[i].v);
            if(!(u^v))
                continue;
            f[v]=u;
            if(!(bin(s)^bin(t)))
                break;
        }
        if(bin(s)^bin(t)){
            if(!(k^1)){
                puts("IMPOSSIBLE");
                return 0;
            }
            break;
        }
        if(mx*e[k].w>=mn*e[i].w)
            mx=e[i].w,
            mn=e[k].w;
    }
    t=gcd(mx,mn);
    if(!(t^mn))
        printf("%d
",mx/mn);
    else
        printf("%d/%d
",mx/t,mn/t);
    return 0;
}
原文地址:https://www.cnblogs.com/keshuqi/p/6061173.html