CODE[VS] 1001 舒适的路线

博客详细解析了CODEVS在线编程平台上的第1001题,内容涵盖问题描述、解题思路、代码实现等方面,主要使用C语言进行解答。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:http://codevs.cn/problem/1001/
题解:

#include <stdio.h>

#define MaxN 500
#define MaxM 5000
#define MaxANS 0x3fffffff * 1.0

//定义全局变量道路结构体
typedef struct _Road {
    int xi;     //景点x 
    int yi;     //景点y 
    int vi;     //速度v 
} Road; 
Road roads[MaxM];
//定义全局变量景点集 
int set[MaxN + 1];

//交换道路
void swap(int a, int b) {
    Road tmp;
    tmp = roads[a];
    roads[a] = roads[b];
    roads[b] = tmp;
} 
//按速度顺序对所有道路进行排序
void sort(int m) {
    int i, j;
    //冒泡排序 
    for(i = 0; i < m; i++) {
        for(j = i + 1; j < m; j++) {
            if(roads[i].vi > roads[j].vi) {
                swap(i, j);
            }
        }
    }
} 
//求最大公约数 
int gcd(int a, int b)
{
    return (((a % b) == 0) ? b : gcd(b, (a % b)));  
}

// 并查集 - 查询 
int find(int x) {
    int r = x;      //根节点值
    int t;
    //返回根节点值r 
    while(r != set[r]) { 
        r = set[r];
    } 
    //压缩路径
    t = x;
    while(r != x) {
        t = set[x];
        set[x] = r;
        x = t;
    } 
    //返回根节点值r
    return r; 
}
// 并查集 - 合并
void union_set(int a, int b) {
    int fa = find(a);
    int fb = find(b);
    //如果根节点值不同,则合并两集合
    if(fa != fb) {
        set[fa] = fb;
    } 
} 

int main(int argc, char *argv[]) {
    int n, m;           //景点数,道路数
    int xi, yi, vi;     //道路连接景点x, y和速度v
    int s, t;           //起始景点,目的景点 
    int min, max, ansmin, ansmax;   //当前路径最小值,最大值,最终最小值,最大值 
    double ans;         //当前路径最大值,最小值比值 
    int i, j;           //索引值

    //获取数据
    scanf("%d %d", &n, &m);
    if((n <= 1 || n > MaxN) || (m <= 0 || m > MaxM)) {
        return 1;
    }
    for(i = 0; i < m; i++) {
        scanf("%d %d %d", &xi, &yi, &vi);
        if((xi < 1 || xi > n) || (yi < 1 || yi > n) || vi <= 0) {
            return 1;
        }
        roads[i].xi = xi;
        roads[i].yi = yi;
        roads[i].vi = vi;
    }
    scanf("%d %d", &s, &t);
    if((s < 1 || s > n) || (t < 1 || t > n) || (s == t)) {
        return 1;
    } 
    //排序道路
    sort(m);
    ans = MaxANS;
    //搜索所有道路
    for(i = 0; i < m; i++){
        //初始化并查集
        for(j = 1; j <= n; j++) {
            set[j] = j;
        } 
        //设置当前最小速度
        min = roads[i].vi;
        //遍历道路,合并景点 
        for(j = i; j < m; j++) {
            //更新当前最大速度 
            max = roads[j].vi;
            //合并相连景点 
            union_set(roads[j].xi, roads[j].yi);
            //如果起始点s和目标点t已联通,结束搜索
            if(find(s) == find(t)) {
                //更新最舒适结果
                if((max * 1.0) / (min * 1.0) < ans) {
                    ans = (max * 1.0) / (min * 1.0);
                    ansmin = min;
                    ansmax = max;
                } 
                break;
            } 
        } 
    } 
    //检查是否有最舒适路径
    if(ans == MaxANS) {
        printf("IMPOSSIBLE");
    } 
    else {
        //最终值是整数
        if(ansmax % ansmin == 0) {
            printf("%d", ansmax / ansmin);
        } 
        else {
            printf("%d/%d", ansmax/gcd(ansmax, ansmin), ansmin/gcd(ansmax, ansmin));
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值