codevs 1001 舒适的路线 玄学方法 解题报告

题目描述 Description

Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。
Z小镇附近共有
N(1

输入描述 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

思路

我们可以先把边排序,然后我们想一下,我们要求一条路,这条路上的最大值和最小值的比值最小,那么显然,我们应该是最大值一定的情况下,最小值尽可能的大。所以我们排完序之后,我们从长边到短边开始枚举最大边,然后我们从这条边开始往下枚举,每次把边的两点联通,然后判断起点终点是否联通,如果联通,则用当前选取的最大边和最小边尝试更新答案。最后求出最优情况下最大边和最小边的大小之后,如果不能整除,gcd一下搞成分数就行了!

代码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
struct lx
{
    int x,y,w;
};
bool operator < (const lx &x,const lx &y)
{
    return x.w > y.w;
}
int n,m,s,t,fa[1000],size[1000],maxn,minn,amaxn,aminn;
double pmin;
lx sz[10001];
bool lt;
int getfa(int x)
{
    if (fa[x]==x) return x;
    return fa[x]=getfa(fa[x]);
}
void merge(int x,int y)
{
    if (getfa(x)==getfa(y)) return ;
    int s1=getfa(x),s2=getfa(y);
    if (size[s1]<size[s2])
    {
        fa[s1]=s2;
        size[s2]+=size[s1];
    }
    else
    {
        fa[s2]=s1;
        size[s1]+=size[s2];
    }
}
void init()
{
    for (int i=1;i<=n;i++)
    fa[i]=i,size[i]=1;
}
int gcd(int x,int y)
{
    return !y?x:gcd(y,x%y);
}
int main()
{
    pmin=9999999999999.0;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    scanf("%d%d%d",&sz[i].x,&sz[i].y,&sz[i].w);
    scanf("%d%d",&s,&t);
    sort(sz+1,sz+m+1);
    for (int i = 1;i < m;i++)
    {
        init();
        maxn=sz[i].w;
        merge(sz[i].x,sz[i].y);
        if (getfa(s)==getfa(t))
        {
            amaxn=sz[i].w;
            aminn=sz[i].w;
            lt=true;
            break;
        }
        minn=0;//就是开始在这个位置没有初始化 
        for (int j=i+1;j<=m;j++)
        {
            merge(sz[j].x,sz[j].y);
            if (getfa(s)==getfa(t))
            {
                lt=true;
                minn=sz[j].w;
                break;
            }
        }
        double t1=maxn,t2=minn;
        if (minn)//这个位置也没有判0 
        if ((t1/t2)<pmin)
        {
            pmin=t1/t2;
            amaxn=maxn;
            aminn=minn;
        }
    }
    if (!lt) printf("IMPOSSIBLE\n");else
    {
        if (!(amaxn%aminn)) printf("%d\n",amaxn/aminn);else
        {
            int tp=gcd(amaxn,aminn);
            printf("%d/%d\n",amaxn/tp,aminn/tp);
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值