***ABC364:F - Range Connect MST(并查集)

问题陈述

有一个图,它有 N+QN+Q 个顶点,编号为 1,2,…,N+Q1,2,…,N+Q 。最初,该图没有边。

对于这个图,请依次对 i=1,2,…,Qi=1,2,…,Q 执行以下操作:

  • 对于每个满足 Li≤j≤RiLi​≤j≤Ri​ 的整数 jj ,在顶点 N+iN+i 和 jj 之间添加一条代价为 CiCi​ 的无向边。

完成所有操作后,确定图形是否相连。如果相连,求该图的最小生成树的代价。

最小生成树是成本最小的生成树,生成树的成本是生成树中所用边的成本之和。

限制因素
  • 1≤N,Q≤2×1051≤N,Q≤2×105
  • 1≤Li≤Ri≤N1≤Li​≤Ri​≤N
  • 1≤Ci≤1091≤Ci​≤109
  • 所有输入值均为整数。
输出

如果图形是连通的,则打印最小生成树的代价。否则,打印 −1−1 。

做法

题目大意就是区间l到r的点可以和N+i的点连接一条价值为C的边,1<=i<=Q。首先我们如果单纯的把所有边建出来,然后跑最小生成树,那肯定是不行的,会超时。那我们肯定就想先贪心考虑建边代价小的。对于最小生成树,我们只需要连接n-1条边(那Q个点不算)。我们就用并查集维护,若有两个连通块没连接,那我们就连上。

#include<bits/stdc++.h> 
using namespace std;

int n,q;
int fa[2000010];

struct ty{
	int l,r;
	long long c;
};

bool cmp(ty a,ty b){
	return a.c<b.c; 
}

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

void setfa(int x,int y){
	fa[getfa(x)]=getfa(y);
}

int main(){
	scanf("%d%d",&n,&q);
	vector<ty> v(q);
	for(int i=0;i<q;i++){
		scanf("%d%d%lld",&v[i].l,&v[i].r,&v[i].c);
	}
	
	sort(v.begin(),v.end(),cmp); //贪心 
	
	for(int i=1;i<=n;i++) fa[i]=i;
	long long ans=0;
	int cnt=n;
	
	for(int i=0;i<v.size();i++){
		
		ans+=v[i].c;//第一个点和第N+i个点连。必须连接,不然Q个点之间无法联通
		
		for(int j=getfa(v[i].l)+1;j<=v[i].r;j=getfa(j)+1) {//找没连接的两个连通块 
			
			setfa(j-1,j);//大的点做父亲 ,不然无法实现 
			
			ans+=v[i].c;
			
			cnt--;
			
		}
		
	}
	
	if(cnt!=1) cout<<-1;//最小生成树至少要有n-1条边 
	else cout<<ans;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值