2019.3.16 最小生成树之最平衡生成树

题目描述

学习完最小生成树后,老师只给出几道模板题,为了尽快提升自己的编程能力,小C同学给自己出了这样一道题:最平衡生成树。
最平衡生成树是这样定义的,一个有 n 个结点的连通图的生成树包含原图中的所有n个结点,并且最长边与最短边的差值最小。
现在给你一个有n个结点的图,求最平衡生成树中最长边与最短边的差值。

输入

输入第一行为n和m两个正整数,分别表示图的结点数和边数。
以下m行每行包含三个数a,b,w,分别表示每条边的两个端点和边的权值。

输出

输出满足题目要求的最小值,如果找不到最平衡生成树,则输出-1。

样例输入

4 5
1 2 3
1 3 5
1 4 6
2 4 6
3 4 7

样例输出

1

提示

【数据范围】
对于100%的数据,2<=n<=100,0<=m<=n(n-1)/2,w<=10000。 
【样例输入2】 
3 0 
【样例输出2】 
-1


通过最小生成树的学习我们可以知道 一棵固定起点的最小生成树一定是该点的最平衡生成树

因为最小生成树要求边权和最小 当固定某起点(即固定该点开头的某条边)时的一棵最小生成树的最大边也最小

所以我们只需要从小到大枚举每条边为最小边的最小生成树即可

需要注意的是 当以该边为最小边时若剩余边无法构成最小生成树 则可以直接剪枝跳出循环

上代码

#include<iostream>
#include<algorithm>
using namespace std;
int n,m,ans=0x3f3f3f3f,pre[1000005];
struct edge
{
    int u,v,w;
    bool operator<(const edge& o) const
    {
        return w<o.w;//重载小于运算符,按照边权排序
    }
}e[10005];
int f(int a)//找祖先
{
    if(pre[a]==a)return a;
    return pre[a]=f(pre[a]);
}
void u(int a,int b)//合并
{
    int c=f(a),d=f(b);
    if(pre[c]!=pre[d])pre[c]=pre[d];
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    sort(e+1,e+m+1);
    for(int i=1;i<=m;i++)
    {
        int cnt=0,anss=0;//anss为最大边
        for(int j=1;j<=n;j++)pre[j]=j;
        for(int j=i;j<=m&&cnt<n-1;j++)
        {
            int uu=f(e[j].u),vv=f(e[j].v);
            if(f(uu)!=f(vv)) {
                u(uu,vv);
                anss=e[j].w;//所有边权按照从小到大排序,故可以每次更新最大边
                cnt++;
            }
        }
        if(cnt==n-1)ans=min(ans,anss-e[i].w);
        else break;//剪枝,剩余边不足以构成最小生成树
    }
    if(ans==0x3f3f3f3f)puts("-1");//不存在最小生成树
    else printf("%d",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/qxds/p/10584204.html

时间: 2024-08-30 18:00:13

2019.3.16 最小生成树之最平衡生成树的相关文章

2019.3.16 最小生成树之城市改造

题目描述 作为规划局长的你接到了城市C的改造任务:城市中有n个标志性建筑,要在这n个标志性建筑之间修建双向道路,使得这n个标志性建筑之间相互连通,以最大程度地方便游客来访.由于市政府资金有限,所以希望成本尽可能低.建设费用有两种支付方式:1. 施工公司给出m种套餐供选择,每种套餐可以将方案中的所有标志性建筑连通,总花费为Ci:2. 单独铺设两个标志物之间道路,费用为两个标志物之间的欧式距离的平方.现在要求你选择最佳的建设方案(可以选择任意个套餐以及铺设任意条道路). 输入 输入第一行包括两个整数

2019.8.16

T2 water 官方题解: 一个块的水平面高度就是从这个块走出矩形的所有路径上的最 大值的最小值. 相邻块连边,权值为两块的较大值,矩形 边界的块向“矩形外”连边,权值为 max(高度,0). 做最小生成树. 时间复杂度 O(nmlognm). 瓶颈生成树:满足最大的边最小. 最小生成树:也就是最小瓶颈树. 我来说说: 1.为什么能用最小生成树?? 正如题解,一个格子的水是由它流向外围的所有路径中,每条路径上的最大值     的最小值.(木桶原理) 可以用bfs解决. 最小生成树可以求出最小的

[Intern][2019.03.16]针对已有的HTML如何只凭JS改动?

刚入职的时候看到公司用的HTML日志生成工具附带的Panel,工具不够用,找个Fail还要找半天,于是自己琢磨着添砖加瓦.以前也是个半吊子前端工程师,现在可倒好,想要改页面却连页面生成的模板在哪里都不知道,只有通过改动JavaScript才能实现对页面的修改. 固然,操作DOM有原版的 document.getElementsBy 一族,可是它们get的时候不能通过 class 和 标签 来区分,比如: <div class="FAIL"> <tr class=&qu

@CSP模拟2019.10.16 - [email&#160;protected] 垃圾分类

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 为了保护环境,p6pou建设了一个垃圾分类器. 垃圾分类器是一个树形结构,由 n 个垃圾桶和 n-1 条双向传送带组成. 垃圾处理器的编号为 1, 2, ..., n,每条传送带都可以花 1 秒钟将垃圾从一个垃圾桶输送到另一个垃圾桶. 垃圾投放点是编号为 r 的垃圾桶,垃圾总是投放在这

P2502 [HAOI2006]旅行 - 最小生成树【最小比值生成树(雾】

P2502 [HAOI2006]旅行 Sol: 暴力 枚举所有从S到T的路径,然后用maxw/minw更新答案. 时间复杂度:\(O(玄学)\) 正解 观察到边数\(m\leq5000\) 考虑由直接求maxw和minw -> 枚举minw求maxw 由于从S到T的路径上的最大值最小的边一定在最小生成树上(最小生成树的瓶颈路性质),所以我们可以将边从小到大排序,每次枚举边\(e_i\),并将剩下的\(e_i,e_{i+1}\dots e_m\)建最小生成树,当边\(e_k\)使S和T第一次连通时

2019.5.16 课后练习。简易购物车程序

根据之前看过的知识点,以自己的思路先写出了一个程序,后续继续老师的操作再进行优化. 1 salary = int(input("请输入您的工资(单位 元):")) 2 3 print("以下是可购清单:") 4 5 shopping_list = ['','iphone','computer','book','apple_juice','bread','cake']#商品列表 6 commodity_prices = [0,6000,7000,2,3,3,5] #商

2019.10.16&amp;17小结

话说也蛮久没写小结了,主要这两次考试失分严重,还是总结下吧. 10.16 T1 小奇挖矿2 100/0 [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿石交易市场,以便为飞船升级无限非概率引擎. [问题描述] 现在有m+1个星球,从左到右标号为0到m,小奇最初在0号星球. 有n处矿体,第i处矿体有ai单位原矿,在第bi个星球上. 由于飞船使用的是老式的跳跃引擎,每次它只能从第x号星球移动到第x+4号星球或x+7号星球.每到一个星球,小奇会采走该星球上所有的

解题报告-2019.12.16

解题报告-2019.12 题目:6-3[拓展编程题_课后练习3][P215 习题8-三-4] 报数 (20分) 题目详情: 报数游戏是这样的:有n个人围成一圈,按顺序从1到n编好号.从第一个人开始报数,报到m(<n)的人退出圈子:下一个人从1开始报数,报到m的人退出圈子.如此下去,直到留下最后一个人. 本题要求编写函数,给出每个人的退出顺序编号. 函数接口定义:void CountOff( int n, int m, int out[] ); 其中n是初始人数:m是游戏规定的退出位次(保证为小于

2019.2.16线段树模板

#include <stdio.h>#include <algorithm>#include <iostream>#include <string.h>#include <string>using namespace std;const int maxen=5000;int a[maxen+5],st[(maxen<<2)+5]; //a函数为主函数读入的数组,st为需要查询的数的信息,树的空间大小的四倍: void build(in