find the most comfortable road

http://acm.hdu.edu.cn/showproblem.php?pid=1598


主要是用到了并查集和枚举,通过枚举来表示不同的连通状态

题解: 用贪心的策咯将所有的路按照速度从小到大的顺序存储,然后在枚举每一个路 road1与它后边比它速度大的所有路road2,用并查集判断所求的两个点是否联通,如果两个点连通,那么最大值就是现在枚举到的点road2,最小值就是前面road1,如果此时的road2  - road1 更小,更新min = road2 - road1,一直枚举完所有的路;

#include <iostream>  
#include <algorithm>  
#include <cstdio>  
#include <cstring>  
#include <vector>  
using namespace std;  
const int maxn = 1e5+5;  
int n,m;  
int inf = INT_MAX;  
int acount[maxn][20];      
int amount[maxn];  
int pre[maxn];   //并查集  
struct edge{  
    int s,e,speed;  
    edge(int a,int b,int c){  
        s = a,e = b, speed = c;   
     }  
     friend bool operator<(const edge&e1,const edge&e2){  
        return e1.speed < e2.speed;                    //sort按照速度从小到大排序  
     }  
};  
int find(int x){  
    return x ==pre[x] ? x : pre[x]=find(pre[x]);    //并查集找父节点  
}  
int main(){  
    int ans = 0;  
    while(scanf("%d%d",&n,&m)!= EOF){  
        vector<edge>edges;  
        for(int i = 1; i<= m;i++){  
            int s,e,speed;  
            cin>>s>>e>>speed;  
            edges.push_back(edge(s,e,speed));    //初始化  
        }  
        sort(edges.begin(),edges.end());  //将所有的路按照从小到大的顺序存储  
        int start,end;  
        int q;  
        cin>>q;  
        amount[ans]=q;  
        for(int k =0; k < q; k++){  
            cin>>start>>end;     //所求两点  
            int mi = inf;  
            for(int i = 0; i < edges.size();i++){    //枚举 所有的路  
                for(int i2 = 0; i2<= n ;i2++)    
                    pre[i2]=i2;  
                for(int j = i; j <  edges.size();j++){   //枚举从i以后所有的路  
                    int fs = find(edges[j].s);     //从i以后的所有路都要加入并查集中  
                    int fe = find(edges[j].e);  
                    if(fs != fe)  
                        pre[fs]=fe;  
                    if(find(start)==find(end)){    //如果此时start 和 end 恰好连通 我们就可以开始更新mi   
                        mi = min(mi,edges[j].speed-edges[i].speed);          // 因为i是枚举作为第一条路所以最小值是edge[i].speed 而 edge[j].speed 是当前最后枚举的 所以它为最大值  
                    }  
                }  
            }if(mi == inf) acount[ans][k] = -1;else  
        acount[ans][k]=mi;  
        }  
        ans++;  
    }  
  
    for(int i = 0; i < ans ;i++)  
        for(int j =0; j < amount[i];j++)  
            cout<<acount[i][j]<<endl;  
    return 0;  
      
}  

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值