zoukankan      html  css  js  c++  java
  • HDU1598 并查集+枚举

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

    题意:给出一个无向图,每条边代表两点之间的同行速度,给出起点和终点,求出从起点到终点的路径的最小速度差。若无法从起点到终点,则输出-1。

    思路:存储每条边的信息,按速度升序排序。按速度从小到大枚举边,然后依次往构建的树中添加边直到起点和终点在同一集合中。此时,最初添加的边的速度与最后添加的边的速度差为当前构造的路径的速度差,每次枚举结束后更新速度差。第一次枚举结束后若发现无法从起点到达终点,那么可以直接停止枚举。(第一次无法成功时,所有边均已添加到路径中,之后无论如何枚举也不可能构造出从起点到达终点的路径)代码从形式上来看很像kruskal,但并没有构建出最小生成树。所以我觉得真要分类的话,分到并查集中或许会好一些。(本来kruskal就依靠并查集实现)

    #include<bits/stdc++.h>
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    int n, m, pa[205];
    struct Edge
    {
        int u,v,val;
    }eg[1005];
    
    bool cmp(Edge a, Edge b)
    {
        return a.val < b.val;
    }
    
    void init()
    {
        for (int i=1;i<=n;i++)
            pa[i] = i;
    }
    
    int fnd(int x)
    {
        if (pa[x]!=x) pa[x] = fnd(pa[x]);
        return pa[x];
    }
    
    void uni(int x,int y)
    {
        int tx = fnd(x) , ty = fnd(y);
        if (tx!=ty)
            pa[tx] = ty;
    }
    
    int main()
    {
        int q,st,ed; //询问数量,起点,终点
        while (scanf("%d %d",&n,&m)==2)
        {
            for (int i=0;i<m;i++)
            {
                int u,v,val; //边的两个点,边上的速度
                scanf("%d %d %d",&u,&v,&val);
                eg[i].v = v; eg[i].u = u; eg[i].val = val;
            }
            int ans = INF;
            scanf("%d",&q);
            sort(eg,eg+m,cmp); //将边按速度升序排序
            while (q--)
            {
                scanf("%d %d",&st,&ed);
                ans = INF;
                //将ans置为一个较大值,若之后ans不改变说明无法找到从起点到终点的路径
                for (int i=0;i<m;i++)
                {
                    init();
                    for (int j=i;j<m;j++)
                    {
                        uni(eg[j].v,eg[j].u);
                        if (fnd(st) == fnd(ed))
                            ans = min(ans,eg[j].val - eg[i].val); 
                                            //起点与终点相连,更新ans
                    }
                    if (ans==INF) break; //可以结束枚举
                }
                if (ans == INF) printf("-1
    ");
                else printf("%d
    ",ans);
            }
        }
        return 0;
    }
                                    
  • 相关阅读:
    Java Lambda表达式初探
    解开lambda最强作用的神秘面纱
    常用正则表达式
    js,java时间处理
    Java 8新特性探究(二)深入解析默认方法
    Java 8里面lambda的最佳实践
    lambda表达式和闭包
    Lambda语法篇
    lambda表达式
    依赖注入和控制反转的理解
  • 原文地址:https://www.cnblogs.com/bdNestInLastation/p/5749322.html
Copyright © 2011-2022 走看看