codeforces #309 D D. Nudist Beach(浮点数二分+bfs)
题目链接:
点击打开链接
题目大意:
给出一个连通图选取一个子图,给出不能被选中点,每个点的值为(子图的度数/总度数),求一个最小值最大的子图
题目分析:
很显然这是一个二分图,因为如果存在x能选出子图,那么一定存在x2<x也能成立
那么现在如何判断二分的函数才是关键
构造的方法常见的就两种,一种是取空集,然后看见符合条件加到集合中,一种就是取全集,看见不合适的踢出去,这道题适合第二种,找出集合中不符合条件的点剔除去,因为只有剔除取的点相连的点才可能成为新的不符合条件的点,那么如此看来这符合宽搜的罗辑,那么我们就可以通过宽搜解决这一问题
对于浮点数,我总是有一种莫名的恐惧,果然wa了无数次。。。。。还是弱啊,对浮点数缺乏控制力,但还是守住了底线,一定要自己实现的代码ac,虽然耗费了大半天....
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#define MAX 100007
#define eps 1e-9using namespace std;int n,m,k,u,v,cnt;
bool used[MAX];
int num[MAX],total[MAX];
double r[MAX];
bool ban[MAX];
bool res[MAX];
vector<int> e[MAX];int cmp ( double t )
{if ( fabs(t) <= eps ) return 0;return t < 0 ? -1:1;
}void clear ( )
{memset ( ban , 0 , sizeof ( ban ) );memset ( num , 0 , sizeof ( num ) );memset ( total , 0 , sizeof ( total ) );memset ( used , 0 , sizeof ( used ) );for ( int i = 0 ; i < MAX ; i++ )e[i].clear();
}bool check ( double x )
{queue<int> q;memset ( used , 0 , sizeof ( used ) );for ( int i = 1 ; i <= n ; i++ ){r[i] = num[i]*1.0/total[i];if ( ban[i] ) r[i] = -1;if ( cmp(r[i]-x) < 0 ){q.push ( i );used[i] = true;}}//cout << "YES : " <<r[2]-x <<" " << used[2] << endl;cnt = n;while ( !q.empty() ){int u = q.front();q.pop();cnt--;int len = e[u].size();for ( int i = 0 ; i < len ; i++ ){int v = e[u][i];if ( used[v] ) continue;r[v] -= 1.0/total[v];//if ( r[v] < x )if ( cmp ( r[v] - x ) < 0 ){q.push ( v );used[v] = true;}}}return cnt;
}int main ( )
{while ( ~scanf ( "%d%d%d" , &n , &m , &k ) ){clear();for ( int i = 0 ; i < k ; i++ ){scanf ( "%d" , &u );used[u] = true;ban[u] = true;}for ( int i = 0 ; i < m ; i++ ){scanf ( "%d%d" , &u , &v );total[u]++;total[v]++;if ( used[u] || used[v] ) continue;num[u]++;num[v]++;e[u].push_back ( v );e[v].push_back ( u ); }double l = 0 , r = 1 , mid;int times = 100;int ans_cnt;while ( times-- ){mid = (l+r)/2.0;//cout << l << " " << r << endl;if ( check ( mid ) ) {ans_cnt = cnt;for ( int i = 1 ; i <= n ; i++ )res[i] = used[i];l = mid;}else r = mid;}printf ( "%d\n" , ans_cnt );for ( int i = 1 ; i <= n ; i++ )if ( !res[i] ) printf ( "%d " , i );puts("");}
}
codeforces #309 D D. Nudist Beach(浮点数二分+bfs)相关推荐
- Codeforces553 D. Nudist Beach(二分+队列check)
题意: 给定n个点m条边的无向图 现在可以在n个点中选择若干个点,有k个坏点不能选择,设选出的点集为S, 对于集合S中的每个点x,定义x的活跃度为:(S中x的邻居数量)/(x的邻居数量) 现在要使得S ...
- 二分算法详解:整数二分及浮点数二分算法(Binary Search)(含算法模板)
一.二分算法简介 当我们要从一个序列中查找一个元素的时候,最简单无脑的方法就是顺序查找法,但由于在大数据情况下爆炸的时间复杂度而舍弃. 最常见的方法是二分查找,也称折半查找(Binary Search ...
- 二分思想(二分查找,整数二分,浮点数二分)
二分思想之二分查找,整数二分,浮点数二分 二分思想
- (算法-二分)浮点数二分-求一个数的三次方根
(算法-二分)浮点数二分-求一个数的三次方根 题目描述 题目分析 误差分析 二分(当n>=1时) (当0<=n<1时) (当n<0时) 解决方案 题目描述 给定一个浮点数 n, ...
- Codeforces Round #309 (Div. 1)D. Nudist Beach 二分+bfs
题目:http://codeforces.com/contest/553/problem/D 在一个无向图中,有若干坏点,选择一个不包含坏点的集合,使得集合中p值最小的点的p值最大.一个点的p值=集合 ...
- codeforces round 309 div1 Nudist Beach 二分+搜索
题目描述:给出一个有n(1<=n<=1e5)个点m(1<=m<=1e5)条边的无向图,其中有k个点为堡垒,现在要求占领除堡垒外的一些点作为我方据点,未被占领的点视为敌方据点,使 ...
- codeforces 553D Nudist Beach 二分+bfs
題意: 給你n个点,然后让你选出一些点,使得每个点的比率最小值尽量大,让你输出你所选的点. 其中有m个点是不能选的.k条无向边,连接着点与点,保证只有一个连通块). 点x的比率= (点x的邻居,且在你 ...
- Codeforces 553D Nudist Beach(图论,贪心)
Solution: 假设已经选了所有的点. 如果从中删掉一个点,那么其它所有点的分值只可能减少或者不变. 如果要使若干步删除后最小的分值变大,那么删掉的点集中肯定要包含当前分值最小的点. 所以每次删掉 ...
- Codeforces - 1118D2 - Coffee and Coursework (Hard Version) - 二分
https://codeforces.com/problemset/problem/1118/D2 也是很好想的一个二分啦. 验证m的可行性的时候,肯定是把最多咖啡因的咖啡先尽可能平均分到每一天,因为 ...
最新文章
- 从 LRU Cache 带你看面试的本质
- SQL server 行转列 列转行
- C#(Sharp)操作数据库原理及案例精析(强烈建议收藏)
- 安装翻译_百度翻译下载安装官方地址
- linux二进制数据16进制数据转换,[轉]16进制字符文本/二进制文件迷你互转器
- Java程序设计语言基础02:Java中的基本数据类型和运算符
- H3C DHCP中继和RIP配置实验
- oracle 启动_oracle实验--通过gdb工具研究数据库启动过程
- php无限极 left right,PHP超牛逼无限极分类生成树方法
- 少数民族预科计算机基础教材答案,少数民族预科高等数学(普通高等学校少数民族预科教材)...
- 最拼命最努力的时候(转)
- 【LeetCode-SQL】1336. 每次访问的交易次数
- 雷霆传奇linux源码,【雷霆传奇H5服务端】2020.07首发超漂亮大翅膀传奇网页游戏客户端[附超详细搭建教程]...
- pandas按行、按列合并数据
- python开机自启切换每日必应壁纸
- monit 内存 监控_mac系统监控软件Monity for Mac
- Win10、Win11打开远程桌面连接方法
- 基于区域生长的图像分割算法!
- 代理ARP(Proxy Arp)
- 谷粒商城微服务分布式基础篇二—— Spring Cloud Alibaba、Nacos注册与发现