洛谷 P2323 [HNOI2006]公路修建問題 解題報告
阿新 • • 發佈:2018-08-02
noi inf node \n sort 描述 分享 直接 評測
P2323 [HNOI2006]公路修建問題
題目描述
輸入輸出格式
輸入格式:
在實際評測時,將只會有m-1行公路
輸出格式:
思路:
二分答案
然後把每條能加的大邊都加上,然後加小邊
但在洛谷的題解中,沒有采用二分答案而直接先處理k條大邊,再處理小邊的做法我認為是有問題的,歡迎證明或證偽。
Code:
#include <cstdio> #include <algorithm> const int N=10010; const int M=20010; struct node { int u,v,w,id; bool friend operator <(node n1,node n2) { return n1.w<n2.w; } }e1[M],e2[M]; int n,k,m; void init() { scanf("%d%d%d",&n,&k,&m); for(int i=1;i<m;i++) { scanf("%d%d%d%d",&e1[i].u,&e1[i].v,&e1[i].w,&e2[i].w); e2[i].u=e1[i].u;e2[i].v=e1[i].v; e1[i].id=e2[i].id=i; } std::sort(e1+1,e1+m); std::sort(e2+1,e2+m); } int f[N]; std::pair <int,int> ans[N]; int Find(int x){return f[x]=f[x]==x?x:Find(f[x]);} void Merge(int x,int y){f[Find(y)]=Find(x);} bool check(int len) { for(int i=1;i<=n;i++) f[i]=i; int e=0,we=0; for(int i=1;i<m;i++) { if(e1[i].w>len) break; int u=e1[i].u,v=e1[i].v; if(Find(u)!=Find(v)) { Merge(u,v); ans[++e].first=e1[i].id; ans[e].second=1; we++; } } for(int i=1;i<m;i++) { if(e2[i].w>len) break; int u=e2[i].u,v=e2[i].v; if(Find(u)!=Find(v)) { Merge(u,v); ans[++e].first=e2[i].id; ans[e].second=2; } } return e==n-1&&we>=k; } void work() { int l=1,r=30000; while(l<r) { int mid=l+r>>1; if(check(mid)) r=mid; else l=mid+1; } check(l); printf("%d\n",l); std::sort(ans+1,ans+n); for(int i=1;i<n;i++) printf("%d %d\n",ans[i].first,ans[i].second); } int main() { init(); work(); return 0; }
2018.8.2
洛谷 P2323 [HNOI2006]公路修建問題 解題報告