[HNOI2006]公路修建問題
阿新 • • 發佈:2021-08-09
一、題目
二、思路
這題主要考察的是對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; }