【P2323 [HNOI2006]公路修建問題】題解
阿新 • • 發佈:2021-11-17
題目連結
題外話:
一道純最小生成樹的題,能出道藍我也真服了...
本文預設使用kruskal演算法,主要是因為另一種我不會
首先我們先滿足 \(k\) 條一級道路,對所有道路按一級道路造價排序,然後用最小生成樹的做法選出 \(k\) 條邊。
對於剩下的道路按二級造價排序,然後同理繼續選即可。
時間複雜度 \(O(n\log n)\)
需要注意的是題目輸出格式有誤,後面是輸出具體方案。第一個數代表選的邊的編號,第二個數表示一級還是二級道路。
Code:
// Problem: P2323 [HNOI2006]公路修建問題 // Contest: Luogu // URL: https://www.luogu.com.cn/problem/P2323 // Memory Limit: 125 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) #include<bits/stdc++.h> using namespace std; #define int long long inline int read(){int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+ (x<<3)+(ch^48);ch=getchar();}return x*f;} //#define M //#define mo #define N 20010 struct node { int x, y, yi, er, id; }d[N]; struct Node { int x, y; }cnt[N]; int n, m, i, j, k; int fa[N], ans, p, x, y; int dfs(int x) { if(fa[x]==x) return x; return fa[x]=dfs(fa[x]); } bool cmp(node x, node y) { return x.yi<y.yi; } bool Cmp(node x, node y) { return x.er<y.er; } signed main() { // freopen("tiaoshi.in", "r", stdin); // freopen("tiaoshi.out", "w", stdout); n=read(); p=read(); m=read(); for(i=1; i<=n; ++i) fa[i]=i; for(i=1; i<m; ++i) { d[i].x=read(); d[i].y=read(); d[i].yi=read(); d[i].er=read(); d[i].id=i; } sort(d+1, d+m, cmp); for(i=1, j=0; j<p; ++i) { x=dfs(d[i].x); y=dfs(d[i].y); if(x==y) continue; fa[x]=y; ++j; cnt[j].x=d[i].id; cnt[j].y=1; } ans=d[i-1].yi; sort(d+i+1, d+m, Cmp); for(; j<n-1; ++i) { x=dfs(d[i].x); y=dfs(d[i].y); if(x==y) continue; fa[x]=y; ++j; // printf("%lld 2\n", d[i].id); cnt[j].x=d[i].id; cnt[j].y=2; } ans=max(ans, d[i-1].er); printf("%lld\n", ans); for(i=1; i<n; ++i) printf("%lld %lld\n", cnt[i].x, cnt[i].y); return 0; }