YBTOJ H. 4.保留道路

这篇博客主要介绍了如何运用贪心思想解决最小生成树问题。作者首先解释了在理解题目时遇到的困难,然后详细阐述了通过排序边的权重g和s属性,逐步构建最小生成树的过程。在每次添加边时,利用插入排序原理更新边的顺序,并检查是否已达到树的完整状态。最终,通过代码实现展示了这一算法,得出最小生成树的权值之和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

 思路:

拿到题的时候没太看懂了题意,搞了半小时

其实就是运用贪心思想——先将各个边按g的大小排序这样在后面处理时就可以不考虑g了

再来处理s,对于s,我们每一次只新增一条边,在如果处理边的s小于队列中最大s,则可利用插入排序原理将此边加入边的队列,并且每一次处理完之后都生成一次最小生成树,如果最小生成树的边==n-1的花就进行一次ans的赋值

注意:1.队列中边数最大值只能等于n-1,所以每一次完成一次生成树之后,top=使用的边数

2. 对于每一次使用的边,将其队列位置更新(因为之前未使用的边之后也不可能比此时情况更优

完结撒花:)

Code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+10;
struct node{
	ll x,y,g,s;
}e[N];
ll n,m,fa[N],top,p[N];
ll wwg,wws;
int find(int x){
	if(fa[x]==x) return x;
	else return fa[x]=find(fa[x]);
}
bool cmp(node a,node b){
	return a.g<b.g;
}
int main(){
	ll ans=1e18;
	scanf("%lld%lld%lld%lld",&n,&m,&wwg,&wws);
	for(ll i=1;i<=m;i++){
		scanf("%lld%lld%lld%lld",&e[i].x,&e[i].y,&e[i].g,&e[i].s);
	}
	sort(e+1,e+1+m,cmp);
	for(ll i=1;i<=m;i++){
		for(ll k=1;k<=n;k++) fa[k]=k;
		ll j;
		for(j=top;j>=1;j--){
			if(e[p[j]].s>e[i].s){
				p[j+1]=p[j];
			}
			else break;
		}
		top++;
		p[j+1]=i;
		ll maxg=0,maxs=0,sum=0;
		for(int k=1;k<=top;k++){
			ll xx=find(e[p[k]].x),yy=find(e[p[k]].y);
			if(xx!=yy){
				fa[xx]=yy;
				maxg=max(e[p[k]].g, maxg);
				maxs=max(e[p[k]].s, maxs);
				p[++sum]=p[k];
			}
		}
		if(sum==n-1) 
			ans=min(ans, wwg*maxg+wws*maxs);
		top=sum;//不要忘了 
	}
	if(ans==1e18) puts("-1");
	else printf("%lld",ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值