POJ2349二分+并查集,类似最小树的贪心
题意:
给你n个点,你的任务是构建一颗通讯树,然后给你一个s表示可以选出来s个点两两通讯不花钱,就是费用是0,其他的费用就是两点的距离,有个要求就是其他的费用中最大的那个最小。
思路:
方法比较多,题目也不难,但是容易有一个误区就是很多人认为这个题目是在求最小生成树,我不是这么想的(虽然这个题目可以用最小树的算法过,但是我的感觉是他和最小树是相同的代码,不同的思想),因为最小树毕竟是求全局和的最小,而这个题目是求全局中最大的最小,这样首先容易让人想到的就是直接二分,二分距离,然后去用并查集或者是搜索啥的去判断联通快个数啥的,这样是很容易理解的,我试了下,可以ac,但是回来说最小树,这个题目直接用最小树的算法也可以ac,但是思路和最小树的想法没啥关系,在克鲁斯卡尔里,大体思想是 排序后
如果当前这两个连通块没有连接,那么就直接用最小的代价,也就是当前的花费去连接,因为早晚都得连接,不如趁现在最省的时候,就这样贪心到最后就是最下生成树,但是这个题目的想法却是,既然你是求最大的最小,那么我们排序后就一个一个往里面添加,知道满足要求的时候就直接停止就行了。和最小树的写法没啥区别,但是理论依据不同,这个要清楚。还有就是我用两种方法写了下(还可以有更多方法,什么二分+搜索啥的都行),其中一个是类似最小树那样,另一个是二分+并查集,我的二分里面没啥大优化,如果像更快的话,二分的时候可以直接二分任意两点所有的距离,就是说答案肯定是任意两点距离中的一个,这样可以缩短二分范围。。。。。
二分+并查集
#include<math.h>
#include<stdio.h>
#include<algorithm>
#define eps 0.000001
using namespace std;
typedef struct
{
int x ,y;
}NODE;
typedef struct
{
int a ,b;
double c;
}EDGE;
NODE node[500+5];
EDGE edge[500*500/2+10];
int mer[500+5] ,n ,m;
bool camp(EDGE a ,EDGE b)
{
return a.c < b.c;
}
int finds(int x)
{
return x == mer[x] ? x : mer[x] = finds(mer[x]);
}
bool ok(int nowid ,double now)
{
for(int i = 1 ;i <= n ;i ++)
mer[i] = i;
int s = 0;
for(int i = 1 ;i <= nowid ;i ++)
{
if(edge[i].c > now) break;
int x = finds(edge[i].a);
int y = finds(edge[i].b);
if(x == y) continue;
s ++;
mer[x] = y;
if(s + m >= n) return 1;
}
return 0;
}
double Search2(int nowid)
{
double low = 0 ,up = edge[nowid].c;
double mid;
while(up - low >= eps)
{
mid = (low + up) / 2;
if(ok(nowid ,mid))
up = mid - eps;
else low = mid + eps;
}
return low;
}
double GetDis(NODE a ,NODE b)
{
double x = (a.x - b.x) * (a.x - b.x);
double y = (a.y - b.y) * (a.y - b.y);
return sqrt(x + y);
}
int main ()
{
int t ,i ,j ,nowid;
scanf("%d" ,&t);
while(t--)
{
scanf("%d %d" ,&m ,&n);
nowid = 0;
for(i = 1 ;i <= n ;i ++)
{
scanf("%d %d" ,&node[i].x ,&node[i].y);
for(j = 1 ;j < i ;j ++)
{
++nowid;
edge[nowid].a = i;
edge[nowid].b = j;
edge[nowid].c = GetDis(node[i] ,node[j]);
}
}
if(m >= n)
{
printf("0.00\n");
continue;
}
sort(edge + 1 ,edge + nowid + 1 ,camp);
printf("%.2lf\n" ,Search2(nowid));
}
return 0;
}
贪心+并查集
#include<math.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef struct
{
int a ,b;
double c;
}EDGE;
typedef struct
{
int x ,y;
}NODE;
NODE node[500+5];
EDGE edge[500*500/2+10];
int mer[500+5];
bool camp(EDGE a ,EDGE b)
{
return a.c < b.c;
}
int finds(int x)
{
return x == mer[x] ? x : mer[x] = finds(mer[x]);
}
double GetDis(NODE a, NODE b)
{
double x = (a.x - b.x) * (a.x - b.x);
double y = (a.y - b.y) * (a.y - b.y);
return sqrt(x + y);
}
int main ()
{
int t ,n ,m ,i ,j;
scanf("%d" ,&t);
while(t--)
{
scanf("%d %d" ,&m ,&n);
int nowid = 0;
for(i = 1 ;i <= n ;i ++)
{
mer[i] = i;
scanf("%d %d" ,&node[i].x ,&node[i].y);
for(j = 1 ;j < i ;j ++)
{
++nowid;
edge[nowid].c = GetDis(node[i] ,node[j]);
edge[nowid].a = i ,edge[nowid].b = j;
}
}
if(m >= n)
{
printf("0\n");
continue;
}
sort(edge + 1 ,edge + nowid + 1 ,camp);
int edges = 0;
for(i = 1 ;i <= nowid ;i ++)
{
int x = finds(edge[i].a);
int y = finds(edge[i].b);
if(x == y)continue;
edges ++;
mer[x] = y;
if(edges + m >= n)
{
printf("%.2lf\n" ,edge[i].c);
break;
}
}
}
return 0;
}
POJ2349二分+并查集,类似最小树的贪心的更多相关文章
- HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)
HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...
- 洛谷P2498 [SDOI2012]拯救小云公主 【二分 + 并查集】
题目 英雄又即将踏上拯救公主的道路-- 这次的拯救目标是--爱和正义的小云公主. 英雄来到boss的洞穴门口,他一下子就懵了,因为面前不只是一只boss,而是上千只boss.当英雄意识到自己还是等级1 ...
- 洛谷:P1783 海滩防御(二分+并查集 最短路 最小生成树)
题意: 给定长度为N的海滩,然后有M做防御塔,给出每座塔的位置Xi,到海岸的距离Yi. 求防御塔上最小观测半径Ri,使得海滩被封锁. 思路:要使左边界和右边界连通. 很nice,可以二分+并查集做. ...
- [AGC002D] Stamp Rally 整体二分+并查集
Description 给你一个n个点m个条边构成的简单无向连通图,有Q组询问,每次询问从两个点x,y走出两条路径,使这两条路径覆盖z个点,求得一种方案使得路径上经过的变的最大编号最小. Input ...
- 【BZOJ 1594】 [Usaco2008 Jan]猜数游戏 (二分+并查集)
1594: [Usaco2008 Jan]猜数游戏 Description 为了提高自己低得可怜的智商,奶牛们设计了一个新的猜数游戏,来锻炼她们的逻辑推理能力. 游戏开始前,一头指定的奶牛会在牛棚后面 ...
- bzoj 1196: [HNOI2006]公路修建问题 二分+并查集
题目链接 1196: [HNOI2006]公路修建问题 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1576 Solved: 909[Submit ...
- hdu3081 Marriage Match II(二分+并查集+最大流)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意: n个女生与n个男生配对,每个女生只能配对某些男生,有些女生相互是朋友,每个女生也可以跟她 ...
- 2018.11.02 NOIP模拟 飞越行星带(最小生成树/二分+并查集)
传送门 发现题目要求的就是从下到上的瓶颈路. 画个图出来发现跟去年noipnoipnoip提高组的奶酪差不多. 于是可以二分宽度+并查集检验,或者直接求瓶颈. 代码
- P1783 二分并查集写法
并查集 + 二分 我是 并查集 + 二分 做的QVQ 思路:两两枚举点之间的距离,sort排序,使距离有序.二分答案,每次判断是否符合条件,然后缩小查询范围,直到满足题目要求(保留2位小数精度就为 0 ...
随机推荐
- Mock 框架 Moq 的使用
Mock 框架 Moq 的使用 Intro Moq 是 .NET 中一个很流行的 Mock 框架,使用 Mock 框架我们可以只针对我们关注的代码进行测试,对于依赖项使用 Mock 对象配置预期的依赖 ...
- 如何在 Istio 中支持 Dubbo、Thrift、Redis 以及任何七层协议?
赵化冰,腾讯云高级工程师,Istio Member,ServiceMesher管理委员,Istio 项目贡献者, Aerika 项目创建者 ,热衷于开源.网络和云计算.目前主要从事服务网格的开源和研发 ...
- .NET 5学习笔记(11)—— Host Blazor WebAssembly in a Windows Service
实在是被某软忽悠瘸了,愤而写此一篇.希望能让同样需求的同学们少走弯路.某软在<在 Windows 服务中托管 ASP.NET Core>中,介绍了通过创建Worker Service工程, ...
- 单链表及基本操作(C语言)
#include <stdio.h> #include <stdlib.h> /** * 含头节点单链表定义及基本操作 */ //基本操作函数用到的状态码 #define TR ...
- 关于深度学习配置的一些tips
建立博客的第一天,将以前记录的一些东西存档下,方便查看. 1安装anaconda 2pycharm破解 配置环境变量3虚拟环境推荐是python3.5或3.6版本 4.安装numpy tensorfl ...
- Java中的四种权限修饰符及六种非访问修饰符(简识)
一.是哪四种访问权限修饰符呢? public > protected > [default] > private (公共的 ) (受保护的) (默认的) (私有的) 二.简单认识四种 ...
- Python中的描述器
21.描述器:Descriptors 1)描述器的表现 用到三个魔术方法.__get__() __set__() __delete__() 方法签名如下: object.__get__(self ...
- 使用docker搭建sonarqube
sonarqube是一款代码质量检查工具,使用sonar扫描我们写过的代码,可以有助于检查出代码的bug.规范性和健壮性,有助于提高我们的代码质量. 一.安装docker 安装完成之后,命令行输入 d ...
- FFmpeg API的简单实践应用
0. 前言 利用 FFmpeg 编译链接生成的可执行程序本身可以实现很多特定的功能,但如果我们有自己的个性化需求,想要在自己开发的项目中使用 ffmpeg 的一些功能,就需要理解并应用其已经实现好的A ...
- element Notification 通知文字换行小技巧
this.$notify({ title: "通知", message: res.result, iconClass: "el-icon-bell",//自定义 ...