HDU 1598 find the most comfortable road 枚举 + kruskal算法

/**
*   枚举 + kruskal:
*       因为要找的是一条路的最大值减最小值。 就可以利用kruskal的贪心思想。
*   把所有边按权从小到大(从大到小其实都一样)排序。然后一一枚举,找出所有能使得x和y连通的路径。
*   再在这些路径中找一个舒适度最高的,也就得出答案了。
*       对于这题来说,生成树是不定的,也就是说,只要在贪心的过程中,有x和y在同一集合中,
*   立马break,而根据贪心的思想(或者说,因为数组已经排序),
*   只要把此时的内层循环的nodes[k].w - nodes[i].w 就是这条路径的舒适度。
*/

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#define DEBUG 0
#define INF 0x7fffffff
#define MAXS 1005

typedef long long LL;
using namespace std;

struct Edge {
    int u, v, w;
    bool operator < (const Edge &a) const {
        return w < a.w;
    }
    Edge() {}
    Edge(int uu, int vv, int ww) {u = uu; v = vv; w = ww;}
}edges[MAXS];
int fa[MAXS];

int get_fa(int x) { return x == fa[x] ? x : fa[x] = get_fa(fa[x]); }
void Union(int x, int y) { fa[get_fa(y)] = get_fa(x);}

int main()
{
    int n, m;
    while(scanf("%d%d", &n, &m) != EOF) {
        for(int i = 0; i < m; i ++)
            scanf("%d%d%d", &edges[i].u, &edges[i].v, &edges[i].w);
        sort(edges, edges + m);
        int curMin;
        int x, y, q;  scanf("%d", &q);
        while(q --) {
            scanf("%d%d", &x, &y);
            curMin = INF;
            for(int i = 0; i < m; i ++) {
                /** 初始化父节点,并查集。  */
                for(int j = 1; j <= n; j ++) fa[j] = j;

                int k;
                for(k  = i; k < m; k ++) {
                    Union(edges[k].u, edges[k].v);
                    if(get_fa(x) == get_fa(y))
                        break;
                }
                if(k == m) break;
                if(curMin > edges[k].w - edges[i].w)
                    curMin = edges[k].w - edges[i].w;
            }
            if(curMin == INF)
                printf("-1\n");
            else
                printf("%d\n", curMin);
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值