算法提高-图论- 最小生成树的扩展应用

news2024/11/15 19:57:29

最小生成树的扩展应用

  • 最小生成树的扩展应用
    • AcWing 1146. 新的开始
    • AcWing 1145. 北极通讯网络
    • AcWing 346. 走廊泼水节
    • AcWing 1148. 秘密的牛奶运输

最小生成树的扩展应用

AcWing 1146. 新的开始

利用虚拟源点建图和原题的题意是等价的,因此我们使用虚拟源点建图套最小生成树的模板

//虚拟源点

#include <iostream>
#include <cstring>

const int N = 310;

using namespace std;

int dist[N], w[N][N];
bool st[N];
int n;

int prime()
{
    int res = 0;
    memset(dist, 0x3f, sizeof dist);
    dist[0] = 0;//超级源点入队
    
    
    for(int i = 0; i < n + 1; i ++ )//循环n + 1次(有多少点循环多少次就行了,每次循环确定一条边)
    {
        int t = -1;
        for (int j = 0; j <= n; j ++ )
        {
            if (st[j] == 0 && (t == -1 || dist[t] > dist[j])) t = j;
        }
        
        st[t] = true;
        res += dist[t];
        for (int j = 0; j <= n; j ++ )
        {
            dist[j] = min(dist[j], w[t][j]);
            // if (dist[j] > w[t][j])//不知道为啥这样写不行
            // {
            //     dist[j] = w[t][j];
            // }
        }
    }
    return res;
}

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i ++ )
    {
        cin >> w[0][i];
        w[i][0] = w[0][i];//无向边(事实上最小生成树必须是无向边才可以用prime和kruskal,有向边的最小生成树目前还不知道怎么求)
    }
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= n; j ++ )
            cin >> w[i][j];
            
    cout << prime();
    return 0;
}


AcWing 1145. 北极通讯网络

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

typedef pair<int, int> PII;
#define x first
#define y second

const int N = 510;

struct Edge
{
    int a, b;
    double w;
    bool operator < (const Edge &t) const
    {
        return w < t.w;
    }
}e[N * N];

PII q[N];
int p[N];
int n, k;

double get_dist(PII a, PII b)
{
    int dx = a.x - b.x;
    int dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
}

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];//return x 会wa,必须return p[x]
}

int main()
{
    cin >> n >> k;
    
    for (int i = 0; i < n; i ++ ) p[i] = i;
    
    for (int i = 0; i < n; i ++ ) cin >> q[i].x >> q[i].y;
    
    int m = 0;
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < i; j ++ )//或者这样也行for (int j = 0; j < n && j != i; j ++ )
        {                           //如果j = i就会加入一条长度为0的边,必然影响我们对边的枚举
            e[m ++ ] = {i, j, get_dist(q[i], q[j])};
        }
        
    sort(e, e + m);
    
    int cnt = n;
    double res = 0;
    for (int i = 0; i < m; i ++ )
    {
        if (cnt <= k) break;
        int a = find(e[i].a), b = find(e[i].b);
        if (a != b)
        {
            p[a] = b;
            cnt -- ;
            res = e[i].w;
            
        }
    }
    
    printf("%.2lf", res);
    return 0;
}

AcWing 346. 走廊泼水节

在这里插入图片描述

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 6010;

struct Edge
{
    int a, b, w;
    bool operator < (const Edge &t) const
    {
        return w < t.w;
    }
}e[N];

int p[N], cnt[N];
int n, T;

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main()
{
    cin >> T;
    while (T -- )
    {
        cin >> n;
        for (int i = 1; i <= n; i ++ ) p[i] = i, cnt[i] = 1;
        
        for (int i = 0; i < n - 1; i ++ )//边数为n - 1 因此循环 n - 1
        {
            int a, b, c;
            cin >> a >> b >> c;
            e[i] = {a, b, c};
        }
        
        sort(e, e + n - 1);//n - 1条边
        
        int res = 0;        
        for (int i = 0; i < n - 1; i ++ )
        {
            int a = find(e[i].a), b = find(e[i].b), w = e[i].w;
            
            if (a != b)
            {
                res += (cnt[b] * cnt[a] - 1) * (w + 1);//完全图是每两点之间都有一条边,
                                                       //这里将除了当前的边的其它边都赋值为权值w + 1,
                                                       //这样可以保证每两点之间都有边,
                                                       //并且加完这些边之后还当前的最小生成树没有被改变且唯一
                                                       //(结构没被改变,权值和也没被改变)
                p[a] = b;//将a的所在的集合并入b
                cnt[b] += cnt[a];
                
            }
        }
        cout << res << endl;
    }
    return 0;
}

AcWing 1148. 秘密的牛奶运输

次最小生成树:有两种,一个是相同的权值,另一种是绝对次小生成树,权值是第二小的
求次小生成树有两种方法:第二种方法比较全能
在这里插入图片描述
这题的dfs我是有点晕了,就因该weight是累加的才对呀
在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <cstring>


using namespace std;
typedef long long LL;
const int N = 510, M = 1e4 + 10;

struct Edge
{
    int a, b, w;
    bool f;
    bool operator < (const Edge &t) const
    {
        return w < t.w;
    }
}edge[M];

int h[N], ne[N * 2], e[N * 2], idx, w[N * 2];//用来保存我们用kruskal计算的最小生成树,dfs的时候要用,最小生成树有n-1条边,又是无向边,因此是n * 2
int dist1[N][N], dist2[N][N];
int p[N];
int n, m;

void add (int a, int b, int c)
{
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}

int find(int x)
{
    if(p[x] != x) p[x] = find(p[x]);                                                           
    return p[x];
}

void dfs(int s, int u, int fa, int mw1, int mw2)//s为起点,u为s的邻边,fa为上一个遍历的邻点用来防止回搜,mw1为最长路径,mw2为次长路径
{
    dist1[s][u] = mw1, dist2[s][u] = mw2;//收集上一层计算出来的结果
    
    for(int i = h[u]; ~i; i = ne[i])//本层探究u为起点到其他点的最长路径和次长路径
    {                               //但是我还是不知道为什么它要遍历邻边的邻边,
        int j = e[i], weight = w[i];
        if (j != fa)//防止回搜
        {
            int td1 = mw1, td2 = mw2;
            if (weight > td1) td1 = weight, td2 = mw1;
            else if (mw1 == mw2 || weight > mw2) td2 = weight;//else if(weight <= mw1 && weight > mw2)会wa不知道为啥
            
            dfs(s, j, u, td1, td2);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
        }
    }
}


int main()
{
    // cin >> n >> m;
    scanf("%d%d", &n, &m);
    memset(h, -1, sizeof h);
    for (int i = 0; i < m; i ++ )
    {
        int a, b, c;
        // cin >> a >> b >> c;
        scanf("%d%d%d", &a, &b, &c);
        edge[i] = {a, b, c};
    }
    
    sort(edge, edge + m);
    for (int i = 1; i <= n; i ++ ) p[i] = i;
    
    
    LL sum = 0;//最小生成树的权值和
    //kruskal求最小生成树
    for (int i = 0; i < m; i ++ )
    {
        int a = edge[i].a, b = edge[i].b, w = edge[i].w;//因为a,b还要用,因此不能让 a = find(edge[i].a)
        int pa = find(a), pb = find(b);
        if(pa != pb)
        {
            p[pa] = pb;
            sum += w;
            add (a, b, w), add(b, a, w);
            edge[i].f = true;
        }
        
    }
    
    //以每个点为树的根节点搜索它到其它点的最长路径和次长路径,预处理好这些,方便我们后面给最小生成树“换边”
    for (int i = 1; i <= n; i ++ ) dfs(i, i, -1, 0, 0);
    //for (int i = 1; i <= n; i ++ ) dfs(i, -1, -1e9, -1e9, dist1[i], dist2[i]);
    
    LL res = 1e18;
    
    //遍历一遍所有边,找出不是生成树里面的边,
    //并尝试用它去替换生成树里面两点间的最长路径和次长路径
    //以此来找到次小生成树
    for (int i = 0; i < m; i ++ )
    {
        if (!edge[i].f)//如果该边不是最小生成树里面的边
        {
            int a = edge[i].a, b = edge[i].b, w = edge[i].w;
            LL t;
            if (w > dist1[a][b]) 
                t = sum + w - dist1[a][b];
            else if (w > dist2[a][b]) 
                t = sum + w - dist2[a][b];
            
            res = min(res, t);
        }
    }
    
    printf("%lld\n", res);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/635155.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

主从架构lua脚本-Redis(四)

上篇文章介绍了rdb、aof持久化。 持久化RDB/AOF-Redis&#xff08;三&#xff09;https://blog.csdn.net/ke1ying/article/details/131148269 redis数据备份策略 写job每小时copy一份到其他目录。目录里可以保留最近一个月数据。把目录日志保存到其他服务器&#xff0c;防止机…

服务器网站搭建(一)

文章目录 环境搭建域名购买和解析创建网站环境搭建 一台服务器,我买的腾讯云新加坡的。根据需求选择配置。 重置密码: 自己设置的密码要记住: 登录: 安装宝塔(centos系统),参考官网: https://www.bt

Python 接口测试框架

目录结构定义 首先来看一下项目整体的结构 框架结构 代码结构 Excel 文件结构 代码详细解析 1.工具包 tools 封装操作 excel 方法 excel_operation.py import xlrd from config.config import PROJECT_PATHclass OperationExcel:def __init__(self, file_nameNone, sheet_…

县村快递物流小程序 v1.2.63+前端(本站修复版)

&#x1f388; 限时活动领体验会员&#xff1a;可下载程序网创项目短视频素材 &#x1f388; &#x1f389; 有需要的朋友记得关赞评&#xff0c;文章底部来交流&#xff01;&#xff01;&#xff01; &#x1f389; ✨ 源码介绍 核心功能&#xff1a; 1、县分拣中心入库出库 2…

什么是Vue的脚手架(Vue CLI)?

什么是Vue的脚手架&#xff08;Vue CLI&#xff09;&#xff1f; Vue.js 是一款流行的 JavaScript 框架&#xff0c;用来构建现代的单页面应用程序&#xff08;SPA&#xff09;。Vue.js 的核心库提供了丰富的功能和 API&#xff0c;但是创建一个完整的应用程序需要更多的工具和…

浏览器插件 | Font Picker - 网页字体识别工具

目录 软件简介 Font Picker插件背景 Font Picker插件离线安装教程 Font Picker 小结 软件简介 Font Picker 插件是一款用于 Chrome 浏览器的字体选择器&#xff0c;这种网页字体识别工具看起来非常的干净&#xff0c;使用起来也十分的简单。本文提供Font Picker网页字体…

d3dcompiler_43.dll文件丢失怎么修复,最新修复方法分享

本教程操作系统&#xff1a;Windows系统、 d3dcompiler_43.dll是电脑文件中的dll文件&#xff08;动态链接库文件&#xff09;。如果计算机中丢失了某个dll文件&#xff0c;可能会导致某些软件和游戏等程序无法正常启动运行&#xff0c;并且导致电脑系统弹窗报错。 在我们打开…

【LeetCode】110. 平衡二叉树

110. 平衡二叉树&#xff08;简单&#xff09; 思路 对二叉树做先序遍历&#xff0c;从底至顶返回子树最大高度&#xff0c;若判定某子树不是平衡树则“剪枝”直接向上返回。 递归返回值&#xff1a; 当节点 root 左、右子树的高度差 > 1&#xff1a;返回 -1&#xff0c;代…

吴恩达471机器学习入门课程1第1周

文章目录 1加载数据集2计算COST(均值平方差&#xff0c;1/2m(y_pre - y))3计算梯度4画出成本曲线5梯度下降 import math, copy import numpy as np import matplotlib.pyplot as plt plt.style.use(./deeplearning.mplstyle) from lab_utils_uni import plt_house_x, plt_conto…

OpenMMLab-AI实战营第二期——4-2.MMDetection代码课

文章目录 1. MMDetection介绍&#xff08;vs MMSegmentation&#xff0c;mmdetection3d&#xff09;2. 代码2.1 使用pycocotools配合exif可视化图像2.2 mmdetection中config的继承2.3 mmdet的数据集可视化问题&#xff08;VISUALIZERS&#xff09;2.4 pin_memory参数设置2.5 ma…

康佳液晶电视(非智能)Mstar V56 芯片

&#xfffc;&#xfffc; &#xfffc; &#xfffc; &#xfffc; 2023/6/11 下午8:10:01 康佳用的地面波数字电视解码芯片是&#xff1f; &#xfffc; 2023/6/11 下午8:10:08 康佳电视使用的地面波数字电视解码芯片可能因不同的产品型号而有所不同。然而&#xff0c;根据…

【AI作画】使用DiffusionBee with stable-diffusion在mac M1平台玩AI作画

DiffusionBee是一个完全免费、离线的工具。它简洁易用&#xff0c;你只需输入一些标签或文本描述&#xff0c;它就能生成艺术图像。 DiffusionBee下载地址 运行DiffusionBee的硬性要求&#xff1a;MacOS系统版本必须在12.3及以上 DBe安装完成后&#xff0c;去C站挑选自己喜欢…

ur机器人在moveit中运行环境搭建(保姆级)

ur机器人在moveit中运行环境搭建 我的系统是ubuntu20.04 rosb版本: noetic 1.安装运动学插件 sudo apt-get install ros-noetic-trac-ik-kinematics-plugin 2.安装 eigenpy 需要单独编译,EigenPy是一个用于在Python中使用Eigen库的绑定库 git clone https://github.com/…

[MAUI]写一个跨平台富文本编辑器

文章目录 原理创建编辑器定义实现复合样式选择范围字号字体颜色与背景色字体下划线字体加粗与斜体 序列化和反序列化跨平台实现集成至编辑器 创建控件使用控件最终效果已知问题项目地址 富文本编辑器是一种所见即所得(what you see is what you get 简称 WYSIWYG)文本编辑器&am…

visual studio 2022,ADO.NET 实体数据模型添加 sqlite数据库对象

文章目录 前言前期环境博客github 文档解析文件安装说明文件下载省流版nuget环境配置成功标志sqlite连接测试 前言 我们知道ADO.NET 实体数据模型特别适合动态开发数据库。因为ADO.NET可以使用DB First 开发 我们在开发一个程序的时候&#xff0c;经常会动态更新数据库字段&a…

Python的基础语法知识

1、变量 变量是一个代号&#xff0c;它代表的是一个数据。 在Python中&#xff0c;定义一个变量的操作包含两个步骤&#xff1a; ①为变量起一个名字 ②为变量指定其所代表的数据 这两个步骤在同一行代码中完成。 1.1 变量的命名规则 变量名可以由任意数量的字母、数字、下划…

Unity 简易UI管理器

首先我们需要先定义这么一个UIManager类。 public class UIManager { } UI管理器嘛&#xff0c;顾名思义肯定是用来管理我们游戏中的UI的&#xff0c;而我们游戏当中的UI呢一般是以面板为单位来进行划分的。所以我们还需要一个UI面板类。然后通过我们的UI管理器来管理我们的U…

Linux——创建容器并将本地调试完全的前后端分离项目打包上传docker运行

前言 在上传之前需要有一个已经搭建好的前后端分离的项目&#xff0c;下面是后端的项目结构图和前端页面图 在服务器上利用准备好的docker镜像配置一个新的容器 创建容器 这里使用的docker镜像的OS是ubuntu20.04.需要自备。 注意好端口映射: 通常前端项目使用的端口号一般都…

【DeepSpeed 教程翻译】二,Megatron-LM GPT2,Zero Redundancy Optimizer 和 ZeRO-Offload

文章目录 0x0. 前言0x1. Megatron-LM GPT2使用原始的 Megatron-LM 训练 GPT2设置训练数据运行未修改的Megatron-LM GPT2模型开启DeepSpeed参数解析初始化和训练初始化使用训练API前向传播 反向传播更新模型参数损失缩放检查点保存和加载 DeepSpeed Activation Checkpoints&…

异常检测学习笔记 三、线性回归方法、主成分分析、支持向量机

一、线性回归方法 类似这样的函数是线性回归模型和支持向量机的基础,线性函数很简单,如果原始问题是非线性的,那么将其转化为线性问题更容易处理,比如下面的方程。 线性映射是主成分分析的重要组成部分。 寻找响应(因变量)和解释变量(自变量)之间的线性关系,…