[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;
}


浙公网安备 33010602011771号