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

         还是自己水太浅了T T.自己一开始想的是kijstra,,某同学说会超时,,,就打消了继续进攻的念头。。

  这是一道关于最小生成树的问题。当然就少不了并查集。。主要问题是,什么时候合并,怎样合并。统一合并之后肯定会有一些便被去掉。。这又该怎样处理....一团乱麻抓狂

然后又该怎样求最终结果。。。纠结了好久。

不过,大神就是厉害!!!,参考了他们的思路之后,豁然开朗,合并之后还可以恢复到原来的状态(初始化)。。这就为准备并查集了条件(很好的一个技巧)。然后一个一的比较呗,惊讶的是几层for循环竟然不会超时,不敢想啊惊讶

#include<stdio.h>  
#include<algorithm>  
using namespace std;  
# define INF 99999999  
int n,m;  
int f[300];  
struct note  
{  
    int u,v,w;  
} q[2000];  
void init()  
{  
    for(int i=1; i<=n; i++)  //在后面很重要,初始化的一个重要的条件  
        f[i]=i;  
}  
int cmp(note a,note b)  
{  
    return a.w<b.w;         //排序。。。  
}  
int getf(int v)             //kruskal模板,不需要改  
{  
    if(f[v]==v)  
        return v;  
    else return f[v]=getf(f[v]);  
}  
int merge(int u,int v)  
{  
    int t1,t2;  
    t1=getf(u);  
    t2=getf(v);  
    if(t1!=t2)  
    {  
        f[t2]=t1;  
        return 1;  
    }  
    return 0;  
}  
int main()  
{  
    while(~scanf("%d%d",&n,&m))  
    {  
  
        for(int j=1; j<=m; j++)  
        {  
            scanf("%d%d%d",&q[j].u,&q[j].v,&q[j].w);   //存入数据  
        }  
        sort(q+1,q+m+1,cmp);                           //排序  
        int Q,a,b;                                      
        scanf("%d",&Q);                                 
        while(Q--)                                     //这才是重头戏!!!  
        {  
            scanf("%d%d",&a,&b);                          
            int minn=INF;                              //每读入一次数据要寻找一次最小值,minn要初始化  
            for(int i=1; i<=m; i++)                    //开始枚举喽 从0到m  
            {   
                init();                                //将并查集分开(用词不太准,,)就是回到合并之前的状态。每一次枚举都要....,很重要!!!  
                for(int j=i; j<=m; j++)               //注意这里从i开始==  
                {  
                    merge(q[j].u,q[j].v);             //这是合并每一组。。然后找一组,万一找到了呢^_^  
                    if(getf(a)==getf(b))              //如果他们的父亲相同,就是并查集里已经有了,因为从w小到大排序。不用管a是不是根,b..。  
                        if(minn>q[j].w-q[i].w)        //因为每一次枚举总有a是根的时候,此时minn最小。  
                        {  
                            minn=q[j].w-q[i].w;       //这里有一个小技巧,<span style="font-family: Arial, Helvetica, sans-serif;">q[j].w-q[i].w,因为j大,,排序......</span>  
  
                            break;  
                        }  
                }  
            }  
            if(minn==INF)printf("-1\n");         //没有找到输出-1  
            else printf("%d\n",minn);  
        }  
    }  
    return 0;  
}  


posted on 2017-07-20 14:56  zitian246  阅读(117)  评论(0编辑  收藏  举报