最小生成树拓展应用

news2024/12/23 0:14:46

文章目录

  • 最小生成树拓展应用
      • 理论基础
    • 题单
        • 1. [新的开始](https://www.acwing.com/problem/content/1148/)
        • 2. [北极通讯网络](https://www.acwing.com/problem/content/1147/)
        • 3. [走廊泼水节](https://www.acwing.com/problem/content/348/)
        • 4. [秘密的牛奶运输](https://www.acwing.com/problem/content/1150/)

最小生成树拓展应用

  • 虚拟源点
  • kruskal拓展
  • 次小生成树

理论基础

  1. 任意一棵最小生成树一定可以包含无向图中权值最小的边
  2. 给定一张无向图 G = ( V , E ) , n = ∣ V ∣ , m = ∣ E ∣ G=(V,E),n=|V|,m=|E| G=(V,E),n=V,m=E,从E中选出k<n-1条边构成G的加一个生成森林。若再从剩余的m-k条边中选n-1-k条边添加到生成森林中,使其成为G的生成树,并且选出的边的权值之和最小。则该生成树一定可以包含m-k条边中连接生成森林的两个不连通接节点的权值最小的边

题单

1. 新的开始

第一眼:

  • 要么和其他矿井建立电网共用一个发电站,要么自建发电站
  • 只有当自建站比建电网费用要小时,才自建站
  • 把自环也当成一条边放进去sort,当用不到点时就结束?
  • 已经有电力供应的也可以给其他供应,意思就是进入了生成树就具有供电能力,因此不用担心加进来的边是那个点拉进来的

思考:

感觉是可以prim算法的

  • 为什么prim要过还得有 g [ j ] [ i ] = m i n ( g [ j ] [ i ] , v ) g[j][i]=min(g[j][i],v) g[j][i]=min(g[j][i],v),一篇ac题解

小试牛刀,没过

听y话:

建立一个超级源点,可以解决从哪个点开始的问题,如果只选最小点开始,会把其他自环(也应当看成一条边)忽略而没考虑到

#include<bits/stdc++.h>

using namespace std;
const int N=310,INF=0x3f3f3f3f;
int g[N][N],v[N],d[N],st[N];
int res,n;

void prim(int s){
  memset(d,0x3f,sizeof d);
  d[s]=g[s][s];

  for(int i=1;i<=n;i++){
    int t=-1;
    for(int j=1;j<=n;j++){
      if(!st[j]&&(t==-1||d[t]>d[j])){
        t=j;
      }
    }
    st[t]=1;
    //cout<<t<<","<<d[t]<<' ';
    res+=d[t];
    for(int j=1;j<=n;j++) d[j]=min(d[j],g[t][j]);
  }
}

signed main(){
  cin>>n;
  //memset(g,0x3f,sizeof g);
  int minx=INF,mindex=0;
  for(int i=1;i<=n;i++){
    cin>>g[i][i];
    for(int j=1;j<=n;j++){
      g[j][i]=min(g[j][i],g[i][i]);
    }
    if(minx>g[i][i]){
      mindex=i;
      minx=g[i][i];
    }
  }
  for(int i=1;i<=n;i++){
    for(int j=1;j<=n;j++){
      int x;
      cin>>x;
      if(i!=j) g[i][j]=x;
    }
  }
  prim(mindex);
  //cout<<endl;
  cout<<res<<endl;
  return 0;
}

手搓建立一个超级源点,ac了,prim算法

#include<bits/stdc++.h>

using namespace std;
int n;
const int N=310;
int g[N][N],st[N],d[N];
int res;

int prim(){
  memset(d,0x3f,sizeof d);
  d[0]=0;
  
  for(int i=0;i<=n;i++){
    int t=-1;
    for(int j=0;j<=n;j++){
      if(!st[j]&&(t==-1||d[t]>d[j])){
        t=j;
      }
    }
    st[t]=1;
    res+=d[t];
    for(int j=0;j<=n;j++) d[j]=min(d[j],g[t][j]);
  }
}


signed main(){
  cin>>n;
  for(int i=1;i<=n;i++){
    int x;
    cin>>x;
    g[0][i]=g[i][0]=x;
  }
  for(int i=1;i<=n;i++){
    for(int j=1;j<=n;j++){
      cin>>g[i][j];
    }
  }
  prim();
  cout<<res<<endl;
  return 0;
}
2. 北极通讯网络

第一眼:

  • 加了k限制的最小生成树,能不能用一个变量去计数呢?
  • 挺复杂的一道题,看的第一遍没懂

听y讲:

  • 涉及到通信问题——”中转“,卫星通信(有限),无线收发器(无限)
  • 用并查集就不需要二分了

思考:

  • 要找到最小的d,那一定是先让小边进入kruskal
  • 关于连通块的问题
    • 并查集
    • bfs和dfs有联想到
  • 有点明白,因为这道题一开始并没有直接相连的点,所有点都是独立的,我们要去找最小生成树的话,在本题用kruskal的时候,枚举一次,连通块的个数就会减一
  • 找到第一个能让剩余连通块个数小于等于k的边就行了

版本一过啦,烙铁~

#include<bits/stdc++.h>

using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
const int N=510,M=N*N;
PII dian[N];
int fa[N];
int n,k;

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

struct edge{
  int x,y;
  double z;
  bool operator<(const edge& M)const{
    return z<M.z;
  }
}e[M];

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

signed main(){
  cin>>n>>k;
  for(int i=1;i<=n;i++) fa[i]=i;
  for(int i=1;i<=n;i++){
    int x,y;
    cin>>x>>y;
    dian[i]={x,y};
  }
  int cnt=0;
  for(int i=1;i<=n;i++){
    for(int j=1;j<=n;j++){
      double dist=get_dis(dian[i],dian[j]);
      e[cnt++]={i,j,dist};
    }
  }
  
  sort(e,e+cnt);
  int count=n;
  double res=0;
  for(int i=0;i<cnt;i++){
    int a=e[i].x,b=e[i].y;
    double c=e[i].z;
    a=find(a),b=find(b);
    if(a!=b){
      fa[a]=b;
      res=c;
      count--;
    }
    if(count<=k){
      break;
    }
  }
  printf("%.2f\n",res);
  return 0;
}
3. 走廊泼水节

第一眼:

  • 何为完全图(俩俩之间有边就是完全图)image-20240627183647506
  • 求的是增加的,而不总的,好像可以kruskal解决,但是得知道完全图是什么意思

听y说:

  • 按照什么样的顺序连接能够得到最小值
  • 新边 < w i w_i wi ❌——》不满足生成树定义
  • 新边 = w i w_i wi ❌——》要求生成树唯一

思考:

  • 关于 新边 〉= w i + 1 w_i+1 wi+1 为什么构造的生成树一定是唯一的
    • 因为你要求最小生成树,如果 w i + 1 w_i+1 wi+1 不唯一,那就意味着有 w i w_i wi可以被添加到里面去,那求的原来的生成树就不是最小生成树了,和原树是一个最小生成树矛盾。
  • 怎么把两个集合的所有点连起来
    • 用并查集维护各连通块点的个数
  • 优质题解image-20240628004028620
#include<bits/stdc++.h>

using namespace std;
int n;
const int N=6e3+10,M=N*N;
int fa[N],psize[N];

struct edge{
  int x,y,z;
  bool operator<(const edge& M)const{
    return z<M.z;
  }
}edges[M];

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

signed main(){
  int t;
  cin>>t;
  while(t--){
    cin>>n;
    for(int i=1;i<=n;i++) fa[i]=i,psize[i]=1;
    for(int i=0;i<n-1;i++){
      int a,b,c;
      cin>>a>>b>>c;
      edges[i]={a,b,c};
    }
		sort(edges,edges+n-1);
    int res=0;
    for(int i=0;i<n-1;i++){
      int a=find(edges[i].x),b=find(edges[i].y),c=edges[i].z;
      if(a!=b){
        res+=((psize[a]*psize[b]-1)*(c+1));
        //因为是还需要多少边,所以原本存在的c不用加
        psize[b]+=psize[a];
        fa[a]=b;
      }
    }
    cout<<res<<endl;
  }
  return 0;
}
4. 秘密的牛奶运输

第一眼:

  • 又是奶牛,又是usaco
  • 费用第二小怎么搞次最小生成树
  • 费用第二严格大于费用最小,距离z代表着成本

思考:

  • 可不可以找到最小生成树的后一条边(这个边需要满足能生成树)当作答案?

  • 啥玩意image-20240628005813618

听y说:

  • image-20240628012126169
  • 注意总长度会爆int,要开long long
#include<bits/stdc++.h>

#define int long long 
using namespace std;
int n,m;
const int N=510, M=1e4+10;
int fa[N],d1[N][N],d2[N][N];
//d1存储的是两点之间路径的最长的边
//d2存储的是两点之间路径的次长的边
int h[N],e[2*N],ne[2*N],w[2*N],idx;
//因为是树的结构,可以看成每个点最多有两个子节点

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

struct edge{
  int x,y,z;
  bool f;
  bool operator<(const edge& M)const{
    return z<M.z;
  }
}es[M];

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

//d1,d2形式参数的类型是一维数组,而实参穿的也是一维数组的地址
void dfs(int u,int father,int dmax1,int dmax2,int d1[],int d2[]){
  d1[u]=dmax1,d2[u]=dmax2;
  for(int i=h[u];~i;i=ne[i]){
    int j=e[i];
    if(j!=father){
      int td1=dmax1,td2=dmax2;
      if(w[i]>td1) td2=td1,td1=w[i];
      else if(w[i]<td1&&w[i]>td2) td2=w[i];
      dfs(j,u,td1,td2,d1,d2);
    }
  }
}

signed main(){
  cin>>n>>m;
  memset(h,-1,sizeof h);
  //memset(d1,0x3f,sizeof d1);
  //memset(d2,0x3f,sizeof d2);
  for(int i=1;i<=n;i++) fa[i]=i;
  for(int i=0;i<m;i++){
    int x,y,z;
    cin>>x>>y>>z;
    es[i]={x,y,z};
  }
  sort(es,es+m);
  //求最小生成树
  int sum=0;
  for(int i=0;i<m;i++){
    int a=es[i].x,b=es[i].y,c=es[i].z;
    int pa=find(a),pb=find(b);
    if(pa!=pb){
      fa[pa]=pb; //这里需要找到各自的父节点然后再创建连接
      sum+=c;
      add(a,b,c),add(b,a,c);
      es[i].f=true;
    }
  }
  //以每个点为根找到其与其他点之间的最远距离?
  for(int i=1;i<=n;i++) dfs(i,-1,-1e9,-1e9,d1[i],d2[i]);
  
  //debug dfs找任意两点之间路径最长边和次长边
  //for(int i=1;i<=n;i++){
  //    cout<<i<<":"<<endl;
  //    int k=h[i];
  //    for(int j=k;~j;j=ne[j]){
  //        cout<<e[j]<<","<<d1[i][e[j]]<<","<<d1[i][e[j]]<<" ";
  //    }
  //    cout<<endl;
  //}
  //为什么debug代码打完就过了?
  
	int res=1e18;
  for(int i=0;i<m;i++){
    bool f=es[i].f;
    int a=es[i].x,b=es[i].y,c=es[i].z;
    if(!f){
      if(c>d1[a][b])
				res=min(res,sum+c-d1[a][b]);
      else if(c>d2[a][b]){
        res=min(res,sum+c-d2[a][b]);
      }
    }
  }
  cout<<res<<endl;
  return 0;
}

后台测试样例

4 4
1 2 1
2 3 2
3 4 1
2 4 2

5

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

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

相关文章

001 SpringMVC介绍

文章目录 基础概念介绍BS和CS开发架构应用系统三层架构MVC设计模式 SpringMVC介绍SpringMVC是什么SpringMVC与Spring的联系为什么要学习SpringMVC 六大组件介绍六大组件(MVC组件其他三大组件)说明 基础概念介绍 BS和CS开发架构 一种是C/S架构&#xff0c;也就是客户端/服务器…

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【15】异步_线程池

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【15】异步_线程池 初始化线程的 4 种方式开发中为什么使用线程池线程池七大参数线程池工作原理常见的 4 种线程池生产中如何使用线程池&#xff1f;CompletableFuture 异步编排—简介业务…

dataX同步SQLserver到MySQL数据

引用datax官方描述&#xff1a; DataX 是阿里云 DataWorks数据集成 的开源版本&#xff0c;在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS…

如何利用“AI交互数字人+展厅”拓展文娱消费空间?

打造新生代潮玩聚集地&#xff0c;打造演艺新空间&#xff0c;促进虚拟现实体验等文娱业态场景创新&#xff0c;成为了当下发展文旅消费新场景的一大重要手段。数字人汇集了虚拟现实、增强现实、全息投影、人工智能、实时传输语音合成等数字技术&#xff0c;可以利用数字人重构…

在等保2.0的合规性审查中,常见的难点和误区有哪些?

在等保2.0&#xff08;即《信息安全技术 网络安全等级保护基本要求》GB/T 22239-2019&#xff09;的合规性审查中&#xff0c;企业和机构经常会遇到一些难点和误区&#xff0c;主要包括以下几个方面&#xff1a; 常见误区 1. “三同步”不同步&#xff1a;等保2.0强调“同步规…

golang生成RSA公钥和密钥

目录 场景 场景一&#xff1a;加密、解密 场景二&#xff1a;微信退款 场景三&#xff1a;SSL证书 为什么是.key和.pem格式的文件 生成密钥、公钥 密钥、公钥保存到文件中 第一个&#xff1a;保存密钥到文件里 第二个&#xff1a;保存公钥到文件里 场景 场景一&#…

AI产品活跃用户排名出炉!文心一言APP国内第一,Kimi疯狂掉队

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/ 6月28日&#xff0c;极光大数据旗下月狐数据发布2024年5月中国生成式AI行业市场热点月度分析报告&#xff0c;披露了国内移动端主流生成式AI应用…

一个AI图片生成工具导航网站

上周末上线了一个AI图片生成工具导航网站&#xff0c;主要是面向AI图片工具这个垂直领域。 https://chatgpt-image-generator.com/ 目标是通过收集当下的一些工具&#xff0c;然后进行分类管理&#xff0c;一方面方便大家发现新的工具&#xff0c;另一方面能够更加有针对性、…

操作系统期末复习(对抽象概念的简单形象化)

操作系统 引论 定义与基本概念&#xff1a;操作系统是计算机硬件与用户之间的桥梁&#xff0c;类似于家中的管家&#xff0c;它管理硬件资源&#xff08;如CPU、内存、硬盘&#xff09;&#xff0c;并为用户提供方便的服务&#xff08;应用程序执行、文件管理等&#xff09;。…

Typora 2024 安装教程

本章教程&#xff0c;介绍一下如何使用Typora 最新版本1.9.4&#xff0c;仅供学习交流&#xff0c;切勿滥用。 一、下载安装包 下载地址&#xff1a;https://www.alipan.com/s/8pvKf5ns6GH 当然&#xff0c;你也可以去官网下载&#xff0c;但是官网有可能随时更新&#xff0c;该…

探索CSS布局:创建一个居中的内嵌方块示例

在网页设计中&#xff0c;布局是至关重要的部分。CSS提供了多种方式来实现元素的布局&#xff0c;包括居中对齐、外边距、内边距等。本文将通过一个简单的示例&#xff0c;介绍如何使用CSS来创建一个居中的内嵌方块&#xff0c;并探讨其背后的布局原理。 HTML 结构 首先&…

【Matlab】-- 飞蛾扑火优化算法

文章目录 文章目录 01 飞蛾扑火算法介绍02 飞蛾扑火算法伪代码03 基于Matlab的部分飞蛾扑火MFO算法04 参考文献 01 飞蛾扑火算法介绍 飞蛾扑火算法&#xff08;Moth-Flame Optimization&#xff0c;MFO&#xff09;是一种基于自然界飞蛾行为的群体智能优化算法。该算法由 Sey…

上市公司绿色投资者原始数据+计算代码(2008-2022年)

数据简介&#xff1a;“绿色”信号&#xff0c;意味着潜在环境风险更低&#xff0c;从而绿色投资者降低了对绿色债券的风险补偿要求&#xff0c;推动了信用利差的收窄。因此&#xff0c;绿色投资者会通过投资者风险意识影响债券信用风险。绿色投资者在推动企业绿色可持续发展方…

江山欧派杯2024全国华佗五禽戏线上线下观摩交流比赛在亳州开幕

6月28日&#xff0c;2024全国华佗五禽戏线上线下观摩交流比赛在安徽省亳州市开幕。 此次比赛是由安徽省亳州市文化旅游体育局和安徽省非物质文化遗产保护中心主办、亳州市华佗五禽戏协会&#xff08;国家级非遗华佗五禽戏保护单位&#xff09;和亳州市传统华佗五禽戏俱乐部&…

GIT版本管理工具轻松入门 | TortoiseGit

目录 一、下载git 二、下载tortoisegit&#xff08;可视化git&#xff09; 三、Git本地仓库创建 四、git克隆 五、添加&#xff0c;提交&#xff0c;推送&#xff0c;拉取 六、分支 七、冲突 八、忽略文件&#xff08;修改gitignore文件&#xff09; 一、下载git 安装…

关于转BigDecimal对象时,精度问题

//浮点型数值Double d 0.0003d;//转BigDecimal对象BigDecimal a new BigDecimal(d);System.out.println(String.format("浮点类型数字:%.4f创建BigDecimal对象并且保留多位小数并且保留多位小数时,精度会变多,结果为%s",d,a.setScale(8, BigDecimal.ROUND_DOWN)));…

高电压技术-冲击高压发生器MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 冲击电压发生器是产生冲击电压波的装置&#xff0c;用于检验电力设备耐受大气过电压和操作过电压的绝缘性能&#xff0c;冲击电压发生器能产生标准雷电冲击电压波形&#xff0c;雷电冲击电压截波,标准操作冲击…

Spring底层原理之bean的加载方式三 用注解声明配置类 以及@Configuration 和 @Component 的区别

bean的加载方式三 用注解声明配置类 我们之前用组件扫描加上注解定义bean 实现了bean的加载 当我们又会发现这个配置文件过于繁琐 我们可以写一个类 不是配置文件而是配置类 我们接下来只需要把这句话的功能写到 配置类里面 这样书写就行 package com.bigdata1421.config;…

Git(涵盖GitHub\Gitee码云\GitLab)

Git(涵盖GitHub\Gitee码云\GitLab) 文章目录 Git(涵盖GitHub\Gitee码云\GitLab)课程介绍Git概述官网介绍版本控制介绍两种版本控制工具集中式版本控制工具分布式版本控制工具 Git工作机制代码托管中心 Git安装和客户端的使用Git常用命令设置用户签名初始化本地库查看本地库状态…

软件构造 | Design Patterns for Reuse and Maintainability

Design Patterns for Reuse and Maintainability &#xff08;面向可复用性和可维护性的设计模式&#xff09; Open-Closed Principle (OCP) ——对扩展的开放&#xff0c;对修改已有代码的封 Why reusable design patterns A design… …enables flexibility to change …