P1195 口袋的天空(联通块个数+最小生成树)

news/2024/11/18 8:41:11/

题目背景

小杉坐在教室里,透过口袋一样的窗户看口袋一样的天空。

有很多云飘在那里,看起来很漂亮,小杉想摘下那样美的几朵云,做成棉花糖。

题目描述

给你云朵的个数 N,再给你 M 个关系,表示哪些云朵可以连在一起。

现在小杉要把所有云朵连成 K 个棉花糖,一个棉花糖最少要用掉一朵云,小杉想知道他怎么连,花费的代价最小。

输入格式

第一行有三个数 N,M,K。

接下来 M 行每行三个数 X,Y,L,表示 X 云和 Y 云可以通过 L 的代价连在一起。

输出格式

对每组数据输出一行,仅有一个整数,表示最小的代价。

如果怎么连都连不出 K 个棉花糖,请输出 No Answer

输入输出样例

输入 #1

3 1 2
1 2 1

输出 #1

1

说明/提示

对于 30% 的数据,1≤N≤100,1≤M≤10^3;

对于 100% 的数据,1≤N≤10^3,1≤M≤10^4,1≤K≤10,1≤X,Y≤N,0≤L<10^4。

解析:因为某些云朵是不能相连的,因此会产生若干个连通块,题目要求K个,我们发现,一个连通块以最小生成树相连,每删除一条边,那么会独立一个点,独自成为一个连通块,因此若初始连通块个数已经大于K或者n<k,那么肯定就无解了,否则我们可以每次删一条边以增加一个连通块,从而达到K个。

做法:每个连通块内部求一个最小生成树,存下树边,最后需要补充x个联通块,那么就从所用树边里从大到小删除x个,这样就是最小代价。

#include <bits/stdc++.h>
using namespace std;
const int N=2e4+5;
typedef pair<int,int> PII;
int n,m,k,cnt,ans;//cnt记录连通块的个数
vector<int> v[N];
bool vis[N];//判断是否访问过
map<PII,int> w;//记录两点间的权值
int f[N];
int find(int x)
{if(f[x]!=x) f[x]=find(f[x]);return f[x];
}
struct node
{int x,y,w;bool operator<(const node&p) const{return w<p.w;}
}tr[N];
vector<int> mx;//记录所有存下来的边
void go(int nod)
{cnt++;queue<int> q;q.push(nod);int num=0;//记录当前连通块的边数vis[nod]=true;vector<int> has;//当前所在连通块包含的点has.push_back(nod);while(q.size()){int u=q.front();q.pop();for(int i=0;i<v[u].size();i++){int j=v[u][i];if(!vis[j]){vis[j]=true;has.push_back(j);q.push(j);}}}//求一次最小生成树for(int i=0;i<has.size();i++){int u=has[i];for(int j=0;j<v[u].size();j++){int p=v[u][j];tr[++num]={u,p,w[{u,p}]};}}sort(tr+1,tr+num+1);for(int i=1;i<=num;i++){int x=tr[i].x,y=tr[i].y,value=tr[i].w;x=find(x),y=find(y);if(x!=y){f[x]=y;ans+=value;mx.push_back(value);}}
}
void solve()
{scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n;i++) f[i]=i;for(int i=1;i<=m;i++){int x,y,value;scanf("%d%d%d",&x,&y,&value);v[x].push_back(y);v[y].push_back(x);if(!w[{x,y}]) w[{x,y}]=w[{y,x}]=value;//存储两点最小的一条边else  w[{x,y}]=w[{y,x}]=min(w[{x,y}],value);}for(int i=1;i<=n;i++) if(!vis[i]) go(i);if(cnt>k||n<k){printf("No Answer\n");//连通块个数大于k必然就是无解了return;}sort(mx.begin(), mx.end());//按权值排个序k-=cnt;//还需要几块for(int i=mx.size()-1;i>=0&&k>0;i--,k--) ans-=mx[i];printf("%d\n",ans);
}
int main()
{int t=1;//scanf("%d",&t);while(t--) solve();return 0;
}

http://www.ppmy.cn/news/1125223.html

相关文章

数据通信——应用层(域名系统)

引言 TCP到此就告一段落&#xff0c;这也意味着传输层结束了&#xff0c;紧随其后的就是TCP/IP五层架构的应用层。操作系统、编程语言、用户的可视化界面等等都要通过应用层来体现。应用层和我们息息相关&#xff0c;我们使用电子设备娱乐或办公时&#xff0c;接触到的就是应用…

ChunJun: 自定义插件

序言 Chunjun的版本兼容可能会有问题,在我们了解了自定义插件后,在修改源码以应对不同的场景就会得心应手了,针对Chunjun1.12.Release版本说明cuiyaonan2000163.com 自定义插件整体流程 从数据流的角度来看ChunJun&#xff0c;可以理解为不同数据源的数据流通过对应的ChunJu…

win使用git(保姆级教程)

序言 上学期间用的git并不多&#xff0c;但是从研三实习以及后面工作来看&#xff0c;git是一项必备技能&#xff0c;所以在此来学习一下。 下载git安装包 打开网站&#xff0c;根据需求来下载&#xff1b;一般按照如下方式进行下载&#xff1a; 然后安装的时候记得按下图勾…

AUTOSAR扫盲贴--不是黑神话【基本概念和方法论】

猴子纵有72搬变化,也跳不出如来的手掌 目录 1. 引言 2. AUTOSAR的基本概念 2.1. AUTOSAR的架构和组成部分 2.2. AUTOSAR的规范和

SkyWalking快速上手(七)——Skywalking UI 界面简介

文章目录 前言1. 仪表盘1.1 指标展示1.2 自定义仪表盘 2. 拓扑图2.1 节点展示2.2 连接展示 3. 追踪3.1 请求链路3.2 请求详情 4. 性能剖析4.1 方法级别性能分析4.2 代码级别性能分析 5. 告警5.1 告警规则设置5.2 告警通知 6. 日志记录6.1 日志展示6.2日志分析6.3代码示例 总结 …

安卓机型不需要解锁bl 不需要root 即可安装模块 框架 VirtualXposed使用步骤分析

​​​​​​安卓玩机教程---全机型安卓4----安卓12 框架xp edx lsp安装方法【一】 安卓系列机型 框架LSP 安装步骤 支持多机型 LSP框架通用安装步骤 通过以上两个博文基本可以了解手机正常安装框架的步骤。但很多机型局限于不能解锁bl和root&#xff0c;那么这些机型能不能使…

visual studio的安装

visual studio是一款很不错的c语言编译器 下载地址&#xff1a;官网 点击后跳转到以下界面 下滑后点击下载Vasual Sutdio&#xff0c;选择社区版即可 选择位置存放下载文件后&#xff0c;即可开始安装 安装时会稍微等一小会儿。然后会弹出这个窗口&#xff0c;我们选择安装位…

更适合程序员体质的PPT制作工具——Slidev

Slidev简介 Slidev是什么 Slidev是一款基于Vue.js的现代化幻灯片制作工具&#xff0c;它可以帮助用户快速、高效地制作出美观、专业的幻灯片。 目前市面上有很多功能丰富的、通用的、所见即所得的幻灯片制作工具&#xff0c;例如 微软 PowerPoint 或 苹果 Keynote. 它们在制…