【bzoj1196】[HNOI2006]公路修建问题
二分答案
验证有一种贪心的思想,就是如果这条路的c1比二分的值还小,那就要果断选择一级公路。
搜过一遍后,如果可供选择的一级公路小于k,就可以直接返回否了。
接下来继续选择,如果可以选到n-1条路,就可以,否则就不可以。
选择道路时,选择的一定是不在一个集合里及不连通的,要用并查集优化。
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 100010 struct Node { int x,y,c1,c2; }a[N<<2]; int n,k,m; int f[N]; int find(int x) { return x==f[x] ? f[x] : f[x]=find(f[x]); } int work(int d) { int ans=0; for (int i=1;i<=n;i++) f[i]=i; for (int i=1;i<=m;i++) if (a[i].c1<=d) { int r1=find(a[i].x),r2=find(a[i].y); if (r1!=r2) f[r1]=r2,ans++; } if (ans<k) return false; for (int i=1;i<=m;i++) if (a[i].c2<=d) { int r1=find(a[i].x),r2=find(a[i].y); if (r1!=r2) f[r1]=r2,ans++; } if (ans==n-1) return true; else return false; } int main() { scanf("%d%d%d",&n,&k,&m); for (int i=1;i<=m;i++) scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].c1,&a[i].c2); int l=0,r=N; while (l<r) { int mid=(l+r)>>1; if (work(mid)) r=mid; else l=mid+1; } if (work(l)) printf("%d",l); else printf("%d",r); return 0; }