• Avito Cool Challenge 2018:D. Maximum Distance (最小生成树)


    题目链接

    题意 :

    给出一个联通图和一些特殊的点,现在定义cost(u,v)为一条从u到v的路径上面边权的最大值 , 

    定义dis(u,v) 为从u到v 路径上面cost 的最小值

    然后求所有特殊点到其他特殊点的最大距离

    题解:

    做这题前,首先思考一件事情,对于一颗树来说点到点的距离是不是就是树上面路径的边权最大值

    我们来证明一下:假设在最小生成树上面的路径cost为w1,另外在原图中还有一条路径从u到v,其cost为w2,那么必然有w2>w1的。那么我们最后的dis一定是w1。

    那么我们现在的目标就是求特殊点到特殊点之间的最大距离。注意一下这里是从一个特殊点到其它所有特殊点的最大距离

    我们根据Kruskal 算法的构建过程 , 在构建树的时候是先构造小的边的 , 所以我们就可以在Kruskal加边的时候更新答案 , 

    我们假设现在有两个集合,现在将其连接起来,当满足两个集合里面都有特殊点时我们就可以更新答案了,否则就不行。

    转载 现在还有一些问题没有解决 , 待后跟新

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 100001;//最大点数
    int c[maxn], N,M,k;//并查集使用
    int cnt;
    bool a[maxn];
    int VAL[maxn];
    struct EDGE{
        int from, to, w;
        bool operator < (const EDGE &rhs) const{
            return this->w < rhs.w;
        };
    }Edge[maxn];//储存边的信息,包括起点/终点/权值
    
    inline void init()
    {
        for(int i=0; i<=N; i++)
            c[i] = i;
        cnt = 0;
    }
    
    inline void AddEdge(int from, int to, int weight)
    {
        Edge[cnt].from = from;
        Edge[cnt].to   = to;
        Edge[cnt].w    = weight;
        cnt++;
    }
    
    int Findset(int x)
    {
        int root = x;
        while(c[root] != root)
            root = c[root];
    
        int idx;
        while(c[x] != root){ /// 路径压缩
            idx = c[x];
            c[x] = root;
            x = idx;
        }
        return root;
    }
    
    int Kruskal()//传入点数,返回最小生成树的权值,如果不连通返回-1
    {
        sort(Edge,Edge+cnt);
        int EdgeCnt=0;//计算加入的边数
        int Cost=0;
         int MAX=0;
        for(int i=0;i<cnt;i++){
            int u=Edge[i].from;
            int v=Edge[i].to;
            int w=Edge[i].w;
            int R1 = Findset(u);
            int R2 = Findset(v);
            if(R1==R2) continue;
            c[R1]=R2;
            if(a[u]) VAL[R1]++;//标记的点
            if(a[v]) VAL[R2]++;
            if(VAL[R1] && VAL[R2] )//如果标记的点都有
            MAX=w;
           VAL[R2]+=VAL[R1];
            EdgeCnt++;
            if(EdgeCnt==N-1) break;
        }
        if(EdgeCnt<N-1) return -1;//不连通
        else return MAX;
    }
    
    
    int main()
    {
            scanf("%d%d%d",&N,&M,&k);
            init();
            int Val;
            for(int i=1 ; i<=k ; i++)
            {
                 scanf("%d",&Val);
                 a[Val]=1;
            }
    
    
             for(int i=1 ; i<=M ; i++)
             {   int u,v,w;
                 scanf("%d%d%d",&u,&v,&w);
                 AddEdge(u,v,w);
             }
             int P=Kruskal();
             for(int i=1 ; i<=k ; i++)
             printf("%d ",P);
          //  printf("%d
    ", Kruskal());
    
        return 0;
    }
    View Code
  • 相关阅读:
    MySQL根据父ID排序类别
    isNotBlank的用法
    IDEA中的.iml文件和.idea文件夹
    java组件:获取查询月份的第一天和最后一天,默认取当前月份
    MyBatis:条件构造器QueryWrapper方法详解
    querywrapper条件构造器
    mybatisplus主键策略选择
    mybatis-plus 高级搜索分页功能的实现 sql语句 QueryWrapper 条件判断
    QueryWrapper查询
    MySQL根据父ID排序类别(mysql sort category according to parent id)
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/10136769.html
Copyright © 2020-2023  润新知