HDU - 1598 find the most comfortable road (枚举+Kruskal算法)

XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超级空中漫游结构)进行交流,每条SARS都对行驶在上面的Flycar限制了固定的Speed,同时XX星人对 Flycar的“舒适度”有特殊要求,即乘坐过程中最高速度与最低速度的差越小乘坐越舒服 ,(理解为SARS的限速要求,flycar必须瞬间提速/降速,痛苦呀 ), 
但XX星人对时间却没那么多要求。要你找出一条城市间的最舒适的路径。(SARS是双向的)。 
Input
输入包括多个测试实例,每个实例包括: 
第一行有2个正整数n (1<n<=200)和m (m<=1000),表示有N个城市和M条SARS。 
接下来的行是三个正整数StartCity,EndCity,speed,表示从表面上看StartCity到EndCity,限速为speedSARS。speed<=1000000 
然后是一个正整数Q(Q<11),表示寻路的个数。 
接下来Q行每行有2个正整数Start,End, 表示寻路的起终点。
Output
每个寻路要求打印一行,仅输出一个非负整数表示最佳路线的舒适度最高速与最低速的差。如果起点和终点不能到达,那么输出-1。
Sample Input
4 4
1 2 2
2 3 4
1 4 1
3 4 2
2
1 3
1 2
Sample Output
1

0

题意:

给定两个正整数N和M,N个城市M条线路,接下来M行每行三个整数表示连通两个城市的双向路的限速,再给Q组整数,为起点和终点。若这两个城市能到达,求出最小限速差(整条路上的最高速减最低速,不是相邻两条路的限速差),不能到达输出“-1”。

解题思路:

应该想到这是个最小生成树问题,并且用Kruskal算法会方便一些。首先将每条路的限速从小到大排序,可以保证在确保能够联通的前提下,最高速与最小速差值最小。将路和限速在结构体(方便排序)里存好后,输入Q组数据。每输入一组,应该用两层for循环更新最小速度差(因为可以连通起点与终点的方案可能不止一个),外层循环i从排好序后的第一条路开始,其实就是假定满足题意要求的最小限速就是这条路的限速,内层循环从外层循环的那条路开始(可能这条路本身就将起点与终点连通),看往后的路是否可以连通起点与终点,当起点与终点连通时更新限速差(就是用连通时的内层循环的那条路的限速减去外层循环的那条路的限速),因为限速已经从小到大排序,所以当起点终点连通时就已经是这种方案的最小限速差了。当外层循环跑完时,各种方案都枚举了一遍,所以更新的限速差就是最小限速差。

AC代码:

#include<stdio.h>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;

int f[210];

struct node  //存储线路与最高限速
{
    int x;
    int y;
    int d;
} Q[10010];

bool cmp( node a, node b )
{
    return a.d < b.d;   //将最高限速从小到大排序
}

int getf( int v )
{
    if( f[v] == v )
        return v;
    else
        return f[v] = getf(f[v]);
}

int pan( int x1, int x2 )
{
    int t1 = getf(x1);
    int t2 = getf(x2);
    if( t1 != t2 )
    {
        f[t2] = t1;
        return 1;
    }
    return 0;
}

int main()
{
    int n, m;
    while( ~scanf("%d%d",&n,&m) )
    {
        for( int i = 1; i <= m; i++ )
            scanf("%d%d%d",&Q[i].x,&Q[i].y,&Q[i].d);
        sort(Q+1,Q+1+m,cmp);           //排序,因为从1开始输入所以下标从1到1+m
        int g, g1, g2;
        scanf("%d",&g);
        for( int c = 1; c <= g; c++ )
        {
            scanf("%d%d",&g1,&g2);
            int  minn = INF;          //初始化最小值
            for( int i = 1; i <= m; i++ ) //假定第i条路为满足要求的最小限速
            {
                for( int k = 1; k <= n; k++ )
                    f[k] = k;
                for( int k = i; k <= m; k++ )//从第i条路往后选择
                {
                    pan(Q[k].x,Q[k].y);
                    if( getf(g1) == getf(g2) )
                    {           //如果起点和终点连通就更新限速差
                        minn = min(minn,Q[k].d-Q[i].d);
                        break;
                    }
                }
            }
            if( minn == INF ) //minn == INF 代表起点到不了终点
                printf("-1\n");
            else
                printf("%d\n",minn);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值