<二分答案加验证||最小生成树>bzoj 1821 部落划分
来源:互联网 发布:js 正则 可有可无 编辑:程序博客网 时间:2024/05/29 18:36
去题面的传送门
Solution 1:
二分答案加验证
并查集维护分成的部落
小于答案的边必须分到同一个并查集里,最后并查集的数目如果小于k,那么答案偏小
这里有一个问题
二分时,如果把各个点之间的距离排一遍序,二分这个数组的话,会wa
原因是,举个栗子:
比如说各点的距离里面,有一段区间是:[11.2145,12.4000],如果直接二分这个区间,在验证到答案11.2145时,发现11.2145符合答案要求,于是去找更大的答案,这时会二分到12.40000甚至比它更大的。但是,题目要求精确到小数点后面两位数字,也就是说,如果11.2169(比11.2145大但是不超过11.2145的数字)是符合答案的,那就错过了这个答案。实际上这组数据的最后答案就是11.21,如果二分数组的话,答案是12.40.
所以对于这种浮点数的精度问题,还是精确一点好
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int maxn=1000+10;int n,k,cnt,tot1,tot2,tot;double ans;int fa[maxn],num[maxn];double d[maxn<<1],dis[maxn][maxn];struct hh{ int x,y;}e[maxn];int find(int x){ if(fa[x]==x) return x; return fa[x]=find(fa[x]);}bool check(double x){ tot=n; for(int i=1;i<=n;++i) fa[i]=i; for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j) { int f1=find(i),f2=find(j); if(dis[i][j]<=x) { if(f1!=f2) { tot--; fa[f1]=f2; } } } if(tot<k) return false; return true;}int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;++i) scanf("%d%d",&e[i].x,&e[i].y); for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j) { int x1=e[i].x,y1=e[i].y,x2=e[j].x,y2=e[j].y; dis[i][j]=dis[j][i]=(double)sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } double l=0,r=10100; while(r-l>0.0001) { double mid=(l+r)/2.0; if(check(mid)) l=mid; else r=mid; } if(check(r)) ans=r; else ans=l; printf("%.2lf",ans); return 0;}
Solution 2:
最小生成树
懒得写了,上题解:
最小生成树——首先将任意两点间的距离处理出来。在一开始时,每个点各为一个集合,在不连边的情况下,那么答案一定是所有的边中最小的边。由于已经推出的贪心的思想,我们连接不在同一个集合内的两点就相当于删去这两个点所在集合内部的任意两点间的边。所以我们把这条最小的边连接,此时答案,又是所有剩余的边中最小的边,然后我们再进行连接(shan chu)……。那么显然——答案一定在最小生成树中。
所以我们可以建立一棵最小生成树,来保证每次连边都是不在同一个集合内的两点且长度为当前最小,直到连接了n-k+1条边。
为什么是n-k+1条??
n-k是为了保证能够建成k个集合(已知n-1条边是一棵树,若删去一条边–>n-2是两棵树……那么n-k就是k棵树啦)
+1的原因是为了保证当前求的这一条边是集合外的边,并不是连接的意思。
这样第n-k+1条边的长度就是答案啦
- <二分答案加验证||最小生成树>bzoj 1821 部落划分
- <考试题> bzoj 1821 部落划分 (二分、最小生成树)
- bzoj 1821 部落划分
- BZOJ 2654 tree(二分答案+最小生成树)
- BZOJ 1821 Group 部落划分 Group【二分+并查集】
- BZOJ 1821 部落划分(二分+并查集)
- bzoj1821: [JSOI2010]Group 部落划分 Group(最小生成树)
- BZOJ 1821 JSOI2010 部落划分 Group Kruskal
- 【BZOJ 1821】 [JSOI2010]Group 部落划分 Group
- bzoj 1821 [JSOI2010]Group 部落划分
- BZOJ 1821 Group 部落划分 Group
- bzoj 1821: [JSOI2010]Group 部落划分
- bzoj 1821: [JSOI2010]Group 部落划分 Group
- BZOJ 1821 [JSOI2010]Group部落划分
- 【bzoj 1821】 [JSOI2010]Group 部落划分 Group
- bzoj2654 Tree 二分答案+最小生成树
- bzoj2654 二分答案+最小生成树
- 修公路 最小生成树 二分答案
- js预处理阶段arguments深度解剖
- NOIP2012 Day2
- java接口的使用
- Druid大数据实时处理的开源分布式系统——Historical Node
- Oracle数据库、实例、用户、表空间、表之间的关系
- <二分答案加验证||最小生成树>bzoj 1821 部落划分
- 腾讯浏览服务接入文档
- iOS AutoLayout 简单运用(纯代码)
- <考试题> codevs 5440 运输计划 (二分+lca+dfs序+树上差分)
- 1701 H2王建瑜 连续第十二天
- 笨方法学习Python-习题19: 函数和变量
- JAVA动态规划,上梯子问题
- java 代理模式的三种用法
- 数据结构上机实践第八周项目6- 猴子选大王(数组版)