题目链接~~>

做题感悟:越来越感觉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的更多相关文章

  1. 【Codeforces 1086B】Minimum Diameter Tree

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 统计叶子节点个数m 把每条和叶子节点相邻的边权设置成s/cnt就可以了 这样答案就是2*s/m(直径最后肯定是从一个叶子节点开始,到另外一个叶 ...

  2. D. Minimum Diameter Tree 思维+猜结论

    D. Minimum Diameter Tree 思维+猜结论 题意 给出一颗树 和一个值v 把该值任意分配到任意边上 使得\(\sum\limits_{i,j}p_{ij}=v\) 使得 这颗树任意 ...

  3. CodeForces 164 B. Ancient Berland Hieroglyphs 单调队列

    B. Ancient Berland Hieroglyphs 题目连接: http://codeforces.com/problemset/problem/164/B Descriptionww.co ...

  4. codeforces ~ 1009 B Minimum Ternary String(超级恶心的思维题

    http://codeforces.com/problemset/problem/1009/B B. Minimum Ternary String time limit per test 1 seco ...

  5. Codeforces 893F - Subtree Minimum Query

    893F - Subtree Minimum Query 题意 给出一棵树,每次询问 \(x\) \(k\),求以 \(x\) 为根结点的子树中的结点到结点 \(x\) 的距离小于等于 \(k\) 的 ...

  6. Codeforces 279D The Minimum Number of Variables 状压dp

    The Minimum Number of Variables 我们定义dp[ i ][ mask ]表示是否存在 处理完前 i 个a, b中存者 a存在的状态是mask 的情况. 然后用sosdp处 ...

  7. 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 ...

  8. Codeforces 805D/804B - Minimum number of steps

    传送门:http://codeforces.com/contest/805/problem/D 对于一个由‘a’.‘b’组成的字符串,有如下操作:将字符串中的一个子串“ab”替换成“bba”.当字符串 ...

  9. 【codeforces 805D】Minimum number of steps

    [题目链接]:http://codeforces.com/contest/805/problem/D [题意] 给你一个字符串; 里面只包括a和b; 让你把里面的"ab"子串全都去 ...

随机推荐

  1. CSDN博客2014年4月24日清理缓存

    亲爱的CSDN博主们.我们将于今天(2014年4月24日)对CSDN博客频道缓存进行清理,假设您登录后发现自己的文章总数.积分.评论数.訪问数出现异常,请不要慌张.您的数据并没有丢失.将会在缓存清理完 ...

  2. JAVA学习第四十五课 — 其它对象API(一)System、Runtime、Math类

    一.System类 1. static long currentTimeMillis() 返回以毫秒为单位的当前时间. 实际上:当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差(以毫 ...

  3. sass09

    scss /* 1.使用自定义function和@each实现栅格布局. @function buildLayout($num: 5){ } 结果: col1{width: 20%} col2{wid ...

  4. hdoj--1408--盐水的故事(技巧)

    盐水的故事 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  5. hpuoj--校赛--面试难题(区间相交问题)

    问题 F: 感恩节KK专场--面试难题 时间限制: 1 Sec  内存限制: 128 MB 提交: 294  解决: 39 [提交][状态][讨论版] 题目描述 有n个人要来面试学生会XX部门,要求面 ...

  6. 12.Intellij IDEA 添加jar包的三种方式

    转自:https://blog.csdn.net/zwj1030711290/article/details/56678353/ 一.直接复制:(不推荐) 方法:直接将硬盘上的jar包复制粘贴到项目的 ...

  7. 编译报错一列----aclocal找不到

    编译源码包报错: 说aclocal这个命令找不到 解决: 使用 yum install -y automake问题解决

  8. 一: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 十进制 ...

  9. 紫书 习题 10-2 UVa 808(建立坐标+找规律)

    这次是我遇见过最迷的一次 我写的程序uDebug全过 和ac程序对拍也过,求出来的坐标是一模一样的,最后结果输出的方式也是一样的 交上去就是错的 迷 第一次遇到这种情况 大佬在哪里 #include& ...

  10. UINavigationBar的系统渲染方式

    昨天想手工实现一下类知乎日报的Navigation Bar的动态颜色改变,但不管怎么设置Navigation Bar的 backgroundColor barTintColor alpha參数都达不到 ...