[HNOI2006]公路修建问题

一、题目

HNOI2006

二、思路

这题主要考察的是对kruskal的应用
大概题意就是要连接至少k条一级公路,因为一级公路的花费一定比二级公路多,所以我们可以先连接k条一级公路,然后剩下的全连二级公路。
具体连法就是先对所有路按一级公路花费来排序,这样能保证连接到的一级公路花费最大的一定是最小的,然后做一遍kruskal
再对二级公路进行排序,将剩下的点用二级公路来连,这样连接到的二级公路花费最大的一定也是最小的,然后做一遍kruskal
在连接公路的时候对ans取max即可获得最终答案

三、代码

#include<bits/stdc++.h>
using namespace std;
int n, k, m;
struct Edge{
	int a, b, cost1, cost2;
}edges[20020];
int ans = 0;
int s[20020];
void init(){
	for(int i = 0; i <= n; i ++){
		s[i] = i;
	}
}
int find(int x){
	if(s[x] != x) return find(s[x]);
	return x;
}
bool merge(int x, int y){
	x = find(x), y = find(y);
	if(x == y) return false;
	s[x] = y;
	return true;
}
bool cmp1(Edge & e1, Edge & e2){
	return e1.cost1 < e2.cost1;
}
bool cmp2(Edge & e1, Edge & e2){
	return e1.cost2 < e2.cost2;
}
void kruskal1(){
	sort(edges + 1, edges + m, cmp1);
	for(int i = 1; i < m && k; i ++){ //这里要注意连接k条一级公路,要多加个k的限制范围
		if(merge(edges[i].a, edges[i].b)){
			ans = max(ans, edges[i].cost1), k --;
		}
	}
}
void kruskal2(){
	sort(edges + 1, edges + m, cmp2);
	for(int i = 1; i < m; i ++){
		if(merge(edges[i].a, edges[i].b)){
			ans = max(ans, edges[i].cost2);
		}
	}
}

int main(){
	cin >> n >> k >> m;
	for(int i = 1; i <= m - 1; i ++){
		cin >> edges[i].a >> edges[i].b >> edges[i].cost1 >> edges[i].cost2;
	}
	init();
	kruskal1();
	kruskal2();
	cout << ans << endl;
	
	
	return 0;
} 
posted @ 2021-08-09 14:56  行舟C  阅读(42)  评论(0)    收藏  举报