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;
    }
                                    
  • 相关阅读:
    二叉树计数2(卡特兰数+高精乘低精+高精除低精)
    奶牛的身高(差分约束)
    海底高铁(差分)
    假期(动态规划+单调队列)
    RY哥查字典(字符串双模hash初步)
    元素查找(hash初步)
    【模板】单源最短路径 堆优化的dijkstra
    【模板】单源最短路径spfa
    【并查集】noi2001食物链
    【带权并查集】银河英雄传说
  • 原文地址:https://www.cnblogs.com/bdNestInLastation/p/5749322.html
Copyright © 2011-2022 走看看