【题解】洛谷P2323 公路修建问题(生成树)

本文深入探讨了最小生成树问题的解决策略,特别是在选择不同级别的公路以构建最优化网络的场景下。通过三个定制的排序函数,文章详细阐述了如何在确保特定数量高级别公路被选用的前提下,找到总成本最高但仍在最小生成树限制内的解决方案。

概括一下 就是最小生成树问题对于连接两个点的一条边都可以选择两个权值(一级 二级),一级权值>=二级,要求必须选至少k条一级公路(因为一级权值始终比二级全职大,所以我们就选k条一级公路),求这样构建出来的最小生成树最长的一条大小与选择第几条公路和级别。

这里我们需要写三个排序函数,第一个按照一级公路权值由小到大排序,选出k条公路。第二个按照二级公路权值由小到大排序,选出n-1-k条公路,记录下来答案需要的值后最后进行第三次排序,按照公路序号由小到大排,输出结果。注意这里枚举的是每一条边后在判断各种条件....之前疯狂WA,还要注意题目给的是m-1条公路,以及调用快排函数时的各种范围(.....)

 

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=10010;
const int maxm=50010;
int n,m,k;
int ans=-100;
int fa[maxn];
struct edge{
	int u,v,w1,w2;
	int t;
}e[maxm*2];
struct print{
	int first;
	int second;
}qwq[maxm*2];
int find(int x)
{
	if(x!=fa[x]) fa[x]=find(fa[x]);
	return fa[x];
}
bool cmp1(const edge &a,const edge &b)
{
	if(a.w1==b.w1) return a.w2>b.w2;
	return a.w1<b.w1;
}
bool cmp2(const edge &a,const edge &b)
{
	return a.w2<b.w2;
}
void kruskal()
{
	int now=0;
	for(int i=1;i<=m;i++)
	{
		int f1=find(e[i].u);
		int f2=find(e[i].v);
		if(f1!=f2)
		{
			fa[f1]=fa[f2];
			ans=max(ans,e[i].w1);
			qwq[now].first=e[i].t;
			qwq[now].second=1;
			now++;
			if(now==k) break;
		}
	}
	sort(e+1,e+m,cmp2);
	for(int i=1;i<=m;i++)
	{
		int f1=find(e[i].u);
		int f2=find(e[i].v);
		if(f1!=f2)
		{
			fa[f1]=fa[f2];
			ans=max(ans,e[i].w2);
			qwq[now].first=e[i].t;
			qwq[now].second=2;	
			now++;
			if(now==n-1) break;
		}
	}
}
bool cmp3(const print &a,const print &b)
{
	return a.first<b.first;
}
int main()
{
	scanf("%d%d%d",&n,&k,&m);
	for(int i=1;i<=m-1;i++)
	{
		scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].w1,&e[i].w2);
		e[i].t=i;
	}
	for(int i=1;i<=n;i++)
	{
		fa[i]=i;
	}
	sort(e+1,e+m,cmp1);
	kruskal();
	sort(qwq,qwq+n-1,cmp3);
	printf("%d\n",ans);
	for(int i=0;i<=n-2;i++)
	{
		printf("%d %d\n",qwq[i].first,qwq[i].second);
	}
	return 0;
}

 

### 关于洛谷 P10466 邻值查找问题的二叉查找树解决方案分析 #### 一、背景介绍 在处理邻值查找问题时,二叉查找树(BST, Binary Search Tree)是一种有效的数据结构。通过构建并维护一棵平衡的二叉查找树,可以实现高效的插入、删除以及查询操作。 #### 二、具体应用到题目中的策略 针对该类问题,在构建二叉查找树的过程中需要注意节点的选择方式及其比较逻辑。当涉及到数值大小关系判断时,应确保遵循左子树小于根节点而右子树大于等于根节点的原则[^1]。这有助于保持树形结构稳定有序,从而支持快速定位目标元素或其最近邻居。 #### 三、代码示例 下面给出一段基于Python语言编写的简单版本二叉查找树实现: ```python class TreeNode: def __init__(self, key=None): self.key = key self.left = None self.right = None def insert(root, value): if root is None: return TreeNode(value) if value < root.key: root.left = insert(root.left, value) elif value >= root.key: root.right = insert(root.right, value) return root def find_nearest_neighbor(root, target_value): current_node = root best_match = None while current_node is not None: if abs(target_value - (current_node.key or float('inf'))) < abs( target_value - (best_match.key if best_match else float('inf'))): best_match = current_node if target_value < current_node.key: current_node = current_node.left else: current_node = current_node.right return best_match and best_match.key # 构建测试用例 test_data_points = [5, 3, 7, 2, 4, 6, 8] bst_root = None for point in test_data_points: bst_root = insert(bst_root, point) print(find_nearest_neighbor(bst_root, 5)) ``` 此段程序展示了如何创建一个基本功能完整的二叉查找树,并提供了`find_nearest_neighbor()`函数用于执行邻近值搜索任务。值得注意的是,为了提高效率和稳定性,实际竞赛编程中可能会采用更复杂的自平衡机制如AVL树或是红黑树等变种形式来代替简单的二叉查找树。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值