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"子串全都去 ...
随机推荐
- CSDN博客2014年4月24日清理缓存
亲爱的CSDN博主们.我们将于今天(2014年4月24日)对CSDN博客频道缓存进行清理,假设您登录后发现自己的文章总数.积分.评论数.訪问数出现异常,请不要慌张.您的数据并没有丢失.将会在缓存清理完 ...
- JAVA学习第四十五课 — 其它对象API(一)System、Runtime、Math类
一.System类 1. static long currentTimeMillis() 返回以毫秒为单位的当前时间. 实际上:当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差(以毫 ...
- sass09
scss /* 1.使用自定义function和@each实现栅格布局. @function buildLayout($num: 5){ } 结果: col1{width: 20%} col2{wid ...
- hdoj--1408--盐水的故事(技巧)
盐水的故事 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...
- hpuoj--校赛--面试难题(区间相交问题)
问题 F: 感恩节KK专场--面试难题 时间限制: 1 Sec 内存限制: 128 MB 提交: 294 解决: 39 [提交][状态][讨论版] 题目描述 有n个人要来面试学生会XX部门,要求面 ...
- 12.Intellij IDEA 添加jar包的三种方式
转自:https://blog.csdn.net/zwj1030711290/article/details/56678353/ 一.直接复制:(不推荐) 方法:直接将硬盘上的jar包复制粘贴到项目的 ...
- 编译报错一列----aclocal找不到
编译源码包报错: 说aclocal这个命令找不到 解决: 使用 yum install -y automake问题解决
- 一:1.1 python程序与数据储存【进制转换】
二进制 :0 1 [逢二进一]0+0=00+1=11+1=1011+1=100 1 1+ 1------ 100 八进制: 0 1 2 3 4 5 6 7 [逢八进一] 1+7=101+2=3 十进制 ...
- 紫书 习题 10-2 UVa 808(建立坐标+找规律)
这次是我遇见过最迷的一次 我写的程序uDebug全过 和ac程序对拍也过,求出来的坐标是一模一样的,最后结果输出的方式也是一样的 交上去就是错的 迷 第一次遇到这种情况 大佬在哪里 #include& ...
- UINavigationBar的系统渲染方式
昨天想手工实现一下类知乎日报的Navigation Bar的动态颜色改变,但不管怎么设置Navigation Bar的 backgroundColor barTintColor alpha參数都达不到 ...