Codeforces 164 D Minimum Diameter
做题感悟:越来越感觉CF的题非常好,非常有深度。
解题思路:
这题须要注意 k 的大小。由于 k 仅仅有 30 个,终于形成的点的直径一定是某个确定的值,所以我们能够枚举这个值。然后把大于这个值的边都取消(删除不大于k 个点),这样不断二分剩下点的最小直径。每次二分的时候推断是否合法。
这里推断是否合法非常重要。由于这须要用dfs去枚举,一不小心就会超时。dfs 在枚举删除每一个点的时候主要枚举两个方面。(1)假设想删除与当前点相连的全部边,能够选择删除全部与之相连的点 (2)能够单独删除此点,然后与之相连的全部边都删除了。这里有一个剪枝:假设以下删除所达到的状态不如上面的优就不继续深搜下去了。由于到达当前点所形成的状态是一样的(都把与1
~ x 节点相连的边都删除了),就看剩下能够删除点多的必然优。
代码:
#include<iostream>
#include<sstream>
#include<map>
#include<cmath>
#include<fstream>
#include<queue>
#include<vector>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<bitset>
#include<ctime>
#include<string>
#include<cctype>
#include<iomanip>
#include<algorithm>
using namespace std ;
#define INT __int64
#define L(x) (x * 2)
#define R(x) (x * 2 + 1)
const int INF = 0x3f3f3f3f ;
const double esp = 0.0000000001 ;
const double PI = acos(-1.0) ;
const int mod = 1e9 + 7 ;
const int MY = 1400 + 5 ;
const int MX = 1010 + 5 ;
int num ,n ,k ;
vector<int>G[MX] ;
int d[MX*MX] ,g[MX][MX] ,vis[MX] ;
struct node
{
int x ,y ;
}P[MX] ;
bool dfs(int cnt ,int m) // cnt 代表编号 。m 代表删除的边数
{
if(cnt > n) return true ;
if(vis[cnt]) return dfs(cnt + 1 ,m) ;
for(int i = 0 ;i < (int)G[cnt].size() ; ++i)
{
m += !vis[G[cnt][i]] ;
vis[G[cnt][i]]++ ;
}
if(m <= k && dfs(cnt + 1 ,m))
return true ;
int temp = m ;
for(int i = 0 ;i < (int)G[cnt].size() ; ++i)
{
vis[G[cnt][i]]-- ;
m -= !vis[G[cnt][i]] ;
}
if(G[cnt].size() != 1)
{
vis[cnt]++ ;
if(m + 1 <= k && m + 1 < temp && dfs(cnt+1 ,m+1))
return true ;
vis[cnt]-- ;
}
return false ;
}
bool judge(int dist)
{
memset(vis ,false ,sizeof(vis)) ;
for(int i = 1 ;i <= n ; ++i)
G[i].clear() ;
for(int i = 1 ;i < n ; ++i)
for(int j = i+1 ;j <= n ; ++j)
if(g[i][j] > dist)
{
G[i].push_back(j) ;
G[j].push_back(i) ;
}
return dfs(1 ,0) ;
}
int binary_search(int le ,int rt) //
{
int mid ;
while(le < rt)
{
mid = (le + rt)>>1 ;
if(judge(d[mid])) rt = mid ;
else le = mid + 1 ;
}
return le ;
}
int main()
{
//freopen("input.txt" ,"r" ,stdin) ;
while(~scanf("%d%d" ,&n ,&k))
{
num = 0 ; d[0] = 0 ;
for(int i = 1 ;i <= n ; ++i)
scanf("%d%d" ,&P[i].x ,&P[i].y) ;
for(int i = 1 ;i < n ; ++i)
for(int j = i+1 ;j <= n ; ++j)
d[++num] = g[i][j] = (P[i].x-P[j].x)*(P[i].x-P[j].x) + (P[i].y - P[j].y)*(P[i].y-P[j].y) ;
sort(d ,d + num + 1) ;
num = unique(d ,d+num+1) - d - 1 ;
int mx = binary_search(0 ,num) ; // 二分查找最小直径
judge(d[mx]) ;
bool first = false ;
for(int i = n ;i >= 1 ; --i)
if(vis[i])
{
if(first) putchar(' ') ;
printf("%d" ,i) ;
k-- ;
first = true ;
}
for(int i = n ;i >= 1 && k > 0 ; --i)
if(!vis[i])
{
if(first) putchar(' ') ;
printf("%d" ,i) ;
k-- ;
first = true ;
}
cout<<endl ;
}
return 0 ;
}
Codeforces 164 D Minimum Diameter的更多相关文章
- 【Codeforces 1086B】Minimum Diameter Tree
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 统计叶子节点个数m 把每条和叶子节点相邻的边权设置成s/cnt就可以了 这样答案就是2*s/m(直径最后肯定是从一个叶子节点开始,到另外一个叶 ...
- D. Minimum Diameter Tree 思维+猜结论
D. Minimum Diameter Tree 思维+猜结论 题意 给出一颗树 和一个值v 把该值任意分配到任意边上 使得\(\sum\limits_{i,j}p_{ij}=v\) 使得 这颗树任意 ...
- CodeForces 164 B. Ancient Berland Hieroglyphs 单调队列
B. Ancient Berland Hieroglyphs 题目连接: http://codeforces.com/problemset/problem/164/B Descriptionww.co ...
- codeforces ~ 1009 B Minimum Ternary String(超级恶心的思维题
http://codeforces.com/problemset/problem/1009/B B. Minimum Ternary String time limit per test 1 seco ...
- Codeforces 893F - Subtree Minimum Query
893F - Subtree Minimum Query 题意 给出一棵树,每次询问 \(x\) \(k\),求以 \(x\) 为根结点的子树中的结点到结点 \(x\) 的距离小于等于 \(k\) 的 ...
- Codeforces 279D The Minimum Number of Variables 状压dp
The Minimum Number of Variables 我们定义dp[ i ][ mask ]表示是否存在 处理完前 i 个a, b中存者 a存在的状态是mask 的情况. 然后用sosdp处 ...
- Codeforces 1082 D. Maximum Diameter Graph-树的直径-最长链-构造题 (Educational Codeforces Round 55 (Rated for Div. 2))
D. Maximum Diameter Graph time limit per test 2 seconds memory limit per test 256 megabytes input st ...
- Codeforces 805D/804B - Minimum number of steps
传送门:http://codeforces.com/contest/805/problem/D 对于一个由‘a’.‘b’组成的字符串,有如下操作:将字符串中的一个子串“ab”替换成“bba”.当字符串 ...
- 【codeforces 805D】Minimum number of steps
[题目链接]:http://codeforces.com/contest/805/problem/D [题意] 给你一个字符串; 里面只包括a和b; 让你把里面的"ab"子串全都去 ...
随机推荐
- hdu5371Hotaru's problem manacher算法
//给一个序列.让求其最大子序列 //这个序列由三段组成.第一段和第二段对称,第一段和第三段一样 //manacher算法求得p[i] //枚举第二段的起点和长度,得到结果 #include<c ...
- java9新特性-13-增强的 Stream API
1.使用说明 Java 的 Steam API 是java标准库最好的改进之一,让开发者能够快速运算,从而能够有效的利用数据并行计算.Java 8 提供的 Steam 能够利用多核架构实现声明式的数据 ...
- 基于分布式的短文本命题实体识别之----人名识别(python实现)
目前对中文分词精度影响最大的主要是两方面:未登录词的识别和歧义切分. 据统计:未登录词中中文姓人名在文本中一般只占2%左右,但这其中高达50%以上的人名会产生切分错误.在所有的分词错误中,与人名有关的 ...
- caffe(7) solver及其配置
solver算是caffe的核心的核心,它协调着整个模型的运作.caffe程序运行必带的一个参数就是solver配置文件.运行代码一般为 # caffe train --solver=*_slover ...
- laravel5.0 自定义服务类
一.创建加密服务类 在 app\services 目录下创建 Encrypt.php <?php namespace App\Services; class Encrypt { } 二.注册服务 ...
- Chrome发布73 beta版:增强Linux用户体验
Google开发者周五推动Chrome 73进入他们的测试频道,因为他们准备在3月12日左右推出这款网页浏览器更新,以便稳定推出.除非另有说明,否则下面描述的更改适用于Android,Chrome O ...
- ArcGIS api for javascript——查询没有地图的数据
描述 本例展示了用户能够从没有显示服务的地图服务查询数据.大部分地图服务包含属性信息的数据集,数据集能够被查询并显示在一个简单的列或表格里. 本例按提供的州名称查询USA人口普查数据,然后显示关于州的 ...
- C++调用Lua的性能測试
游戏服务器经典的架构就是C++和Lua的结合,C++开发主体框架.Lua实现一些复杂的逻辑.我们都知道Lua是一种很快的语言.可是究竟有多块.我们測试下看看. C++调用Lua的性能測试.发现不正确的 ...
- Android:管理应用内存
全部内容均来源于官方文档https://developer.android.com/training/articles/memory.html only way to completely relea ...
- c++动态库中使用命名空间的问题
这是C++才会有的语言特性. 假如你使用一个程序库,他里面有桓霰淞拷衋bc,可是你自己也不小心定义了一个叫abc的变量,这样就会引起重定义错误.所以为了避免这样的现象,C++引入了名字空间(names ...