【问题描述】
在一片草原上有N个兔子窝,每个窝里住着一只兔子,有M条路径连接这些窝。更特殊地是,至多只有一个兔子窝有3条或更多的路径与它相连,其它的兔子窝只有1条或2条路径与其相连。换句话讲,这些兔子窝之前的路径构成一张N个点、M条边的无向连通图,而度数大于2的点至多有1个。
兔子们决定把其中K个兔子窝扩建成临时避难所。当危险来临时,每只兔子均会同时前往距离它最近的避难所躲避,路程中花费的时间在数值上等于经过的路径条数。为了在最短的时间内让所有兔子脱离危险,请你安排一种建造避难所的方式,使最后一只到达避难所的兔子所花费的时间尽量少。

【输入】
第一行有3个整数N,M,K,分别表示兔子窝的个数、路径数、计划建造的避难所数。
接下来M行每行三个整数x,y,表示第x个兔子窝和第y个兔子窝之间有一条路径相连。任意两个兔子窝之间至多只有1条路径。

【输出】
一个整数,表示最后一只到达避难所的兔子花费的最短时间。

【输入输出样例1】

rabbit.in 
5 5 2
1 2
2 3
1 4
1 5
4 5

rabbit.out

1

【输入输出样例1说明】
在第2个和第5个兔子窝建造避难所,这样其它兔子窝的兔子最多只需要经过1条路径就可以到达某个避难所。

【数据规模与约定】
对于30%的数据,N≤15,K≤4;
对于60%的数据,N≤100;
对于100%的数据,1≤K≤N≤1,000,1≤M≤1,500

分析:很明显可以看出这道题要二分,最难的就是要怎么check?假设当前二分的答案是x,我一开始的思路是对于第i个点,将所有与它距离<=x的点打个标记,最后看看能不能有k个点上有所有点的标记.这样就要状压,不好做.换个思路,每个点能覆盖到的点数为2*x+1,处理一下把所有点覆盖需要的点数是不是<=k.可是直接这样处理也非常难,题目中还有一个条件没用上:只有一个度数≥3的点,其它的点的度数≤2,注意≤2这个条件,这说明了一个重要的信息:原图是有一些链和环构成的,都连在一个中心上.

如果没有环,只有链,就很好做了,设当前链的长度为cnt,那么覆盖这条链所需要的点数位cnt / (2*x + 1)上取整.这样我们在距中心点不超过x的一个点上建造一个避难所,把它覆盖到的点给删掉,这时一定会删掉根节点,那么剩下的就成了若干条链,就很好做了.为什么一定要覆盖中心呢?中心其实就相当于一个“中转站”,覆盖的时候经过这个中转站,剩下的距离每一步都能覆盖多个点,如果不经过中心点的话,每一步就只能覆盖一个点,而且这和之前的二分想法没区别,很难处理.

二分想不到如何check的时候,把题目中给的所有限制和人为的限制给列出来,如果不满足某种限制的情况很好求,就针对这个限制进行check,例如本题中的k个避难所.

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int maxn = ; int n, m, k, head[maxn], to[maxn], nextt[maxn], tot = , du[maxn], s;
int d[maxn], vis[maxn], ans, cnt; queue <int> q; void add(int x, int y)
{
to[tot] = y;
nextt[tot] = head[x];
head[x] = tot++;
} void bfs()
{
q.push(s);
vis[s] = ;
d[s] = ;
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = head[u]; i; i = nextt[i])
{
int v = to[i];
if (!vis[v])
{
vis[v] = ;
d[v] = d[u] + ;
q.push(v);
}
}
}
} void dfs(int x, int rest)
{
vis[x] = ;
if (!rest)
return;
for (int i = head[x]; i; i = nextt[i])
{
int v = to[i];
if (!vis[v])
dfs(v, rest - );
}
} void dfs2(int x)
{
cnt++;
vis[x] = ;
for (int i = head[x]; i; i = nextt[i])
{
int v = to[i];
if (!vis[v])
dfs2(v);
}
} bool check(int x)
{
for (int i = ; i <= n; i++)
{
if (d[i] <= x)
{
memset(vis, , sizeof(vis));
dfs(i, x);
int temp = ;
for (int j = ; j <= n; j++)
{
if (!vis[j])
{
cnt = ;
dfs2(j);
temp += cnt / (x * + );
if (cnt % (x * + ))
temp++;
}
}
if (temp <= k)
return true;
}
}
return false;
} int main()
{
scanf("%d%d%d", &n, &m, &k);
for (int i = ; i <= m; i++)
{
int x, y;
scanf("%d%d", &x, &y);
du[x]++;
du[y]++;
add(x, y);
add(y, x);
}
s = ;
for (int i = ; i <= n; i++)
if (du[i] >= )
{
s = i;
break;
}
bfs();
int l = , r = n;
while (l <= r)
{
int mid = (l + r) >> ;
if (check(mid))
{
ans = mid;
r = mid - ;
}
else
l = mid + ;
}
printf("%d\n", ans); return ;
}

noip模拟赛 兔子的更多相关文章

  1. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  2. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  3. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  4. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  5. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  6. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  7. 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  8. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

  9. CH Round #52 - Thinking Bear #1 (NOIP模拟赛)

    A.拆地毯 题目:http://www.contesthunter.org/contest/CH%20Round%20%2352%20-%20Thinking%20Bear%20%231%20(NOI ...

随机推荐

  1. bzoj 1646: [Usaco2007 Open]Catch That Cow 抓住那只牛【bfs】

    满脑子dp简直魔性 模拟题意bfs转移即可 #include<iostream> #include<cstdio> #include<queue> using na ...

  2. P3174 [HAOI2009]毛毛虫(树形dp)

    P3174 [HAOI2009]毛毛虫 题目描述 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大.例如下图左边的树(图 1 )抽出一部分就变成了右边 ...

  3. JSON使用讲解

    前端操作json  一.JSON字符串与JSON对象的区别 1. 一个对象以“{”  开始,     “}”结束.   每个“名称”后跟一个“:”(冒号):“‘名称/值’ 对”之间运用 “,”(逗号) ...

  4. 每天学点Linux命令之Linux-Shell中的数据重定向与管道命令

    在Linux shell中, 数据重定向使用 > < 符号,管道命令使用 | 符号链接前后两个命令. 具体区别如下: 数据重定向 1.(>): 左侧应该有标准输出 > 右侧只能 ...

  5. 从实际案例聊聊Java应用的GC优化--转

    https://tech.meituan.com/jvm_optimize.html 当Java程序性能达不到既定目标,且其他优化手段都已经穷尽时,通常需要调整垃圾回收器来进一步提高性能,称为GC优化 ...

  6. C#,VB.NET将PPT文档转换为HTML

    PPT文档主要用于展示,有时候我们需要将PPT文档转换为HTML格式方便查看.本文将介绍如何使用C#和VB.NET将PPT文档转换为HTML格式.该方案使用了.NET PowerPoint 组件Spi ...

  7. php函数的定义和声明

    1.函数的定义 函数是一个被命名的独立的代码段,它执行特定任务,并可以给调用它的程序返回值. 2.函数的优点 提高程序的重用性 提高程序的可维护性 可以提高软件的开发效率 提高软件的可靠性 控制程序的 ...

  8. [ ZJOI 2010 ] 网络扩容

    \(\\\) Description 给定一张有向图,每条边都有一个容量 \(C\) 和一个扩容费用 \(W\). 这里扩容费用是指将容量扩大 \(1\) 所需的费用.求: 在不扩容的情况下, \(1 ...

  9. 树莓派zero_w设置中文(已成功)

    树莓派默认是采用英文字库的,而且系统里没有预装中文字库,所以即使你在locale中改成中文,也不会显示中文,只会显示一堆方块.因此需要我们手动来安装中文字体. 好在有一个中文字体是免费开源使用的.ss ...

  10. struts2之通配符映射

    系统有n多个请求时候,不可能以一个action对应一个映射.可以用通配符映射将成百上千请求简化成一个通用映射. 通配符映射规则:1.若找到多个匹配,没有通配符的将胜出. 2.若指定的动作不存在,str ...