【问题描述】

在一片草原上有N个兔子窝,每个窝里住着一只兔子,有M条路径连接这些窝。更特殊地是,至多只有一个兔子窝有3条或更多的路径与它相连,其它的兔子窝只有1条或2条路径与其相连。换句话讲,这些兔子窝之前的路径构成一张N个点、M条边的无向连通图,而度数大于2的点至多有1个。

兔子们决定把其中K个兔子窝扩建成临时避难所。当危险来临时,每只兔子均会同时前往距离它最近的避难所躲避,路程中花费的时间在数值上等于经过的路径条数。为了在最短的时间内让所有兔子脱离危险,请你安排一种建造避难所的方式,使最后一只到达避难所的兔子所花费的时间尽量少。

【输入】

第一行有3个整数N,M,K,分别表示兔子窝的个数、路径数、计划建造的避难所数。

接下来M行每行三个整数x,y,表示第x个兔子窝和第y个兔子窝之间有一条路径相连。任意两个兔子窝之间至多只有1条路径。

【输出】

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

【输入输出样例1】

rabbit.in

rabbit.out

5 5 2

1 2

2 3

1 4

1 5

4 5

1

见选手目录下的rabbit / rabbit1.in与rabbit / rabbit1.out

【输入输出样例1说明】

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

【输入输出样例2】

见选手目录下的rabbit / rabbit2.in与rabbit / rabbit2.out

【数据规模与约定】

对于30%的数据,N≤15,K≤4;

对于60%的数据,N≤100;

对于100%的数据,1≤K≤N≤1,000,1≤M≤1,500

/*
求到达时间最晚的兔子的最早到达时间
二分答案X,求解至少建几个避难所,使得每个兔窝在距离X的范围内至少有一个避难所
枚举住在“根”的兔子去往的避难所的位置,记为A
令与A距离不超过X的兔子都前往A
剩下的兔窝被分成若干条链,容易计算最少需要建立几个避难所
判断总数是否超过K个
*/
#include <cstdio>
#include <cstring>
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std; const int maxn = ;
struct data {
int adj, next;
} r[ * maxn];
int g[maxn], tot, du[maxn], rt;
void ins(int a, int b)
{
r[++tot].adj = b;
r[tot].next = g[a];
g[a] = tot;
}
int n, m, k; struct road {
bool circle;
int len;
};
road d[maxn], d2[maxn];
int cnt; int calc(int len, int t)//计算链中需要建造的避难所的数量,每t*2+1个点建一个
{
if (len <= ) return ;
return (len - ) / (t * + ) + ;
} bool check(int t)
{
int mind = n + ;
for (int i = ; i < cnt; ++i)
{
for (int kp = ; kp <= d[i].len && kp <= t; ++kp)
{
int tot;
if (!d[i].circle)
tot = calc(d[i].len - kp - t, t);
else tot = calc(d[i].len - kp - t + (kp - t), t);//注意环的计算,实际上避难所A可以影响到深度比较大的节点
++tot;
for (int j = ; j < cnt; ++j)
if (j != i)
{
if (!d[j].circle)
tot += calc(d[j].len + (kp - t), t);//注意A对他的影响
else
tot += calc(d[j].len + * (kp - t), t);
}
mind = min(mind, tot);
}
}
return mind <= k;
} void binary()
{
int l = , r = n;
while (l < r)
{
int mid = (l + r) >> ;
if (check(mid)) r = mid;
else l = mid + ;
}
printf("%d\n", r);
} void init();
int main()
{
freopen("rabbit.in", "r", stdin);
freopen("rabbit.out", "w", stdout); init();
binary();
return ;
}
bool col[maxn];
int t0;
void dfs(int x)
{
col[x] = ;
++d[cnt].len;
for (int p = g[x]; p != -; p = r[p].next)
if (col[r[p].adj] == )
dfs(r[p].adj);
else if (r[p].adj == rt && x != t0)
d[cnt].circle = ;
}
void init()
{
scanf("%d%d%d", &n, &m, &k);
memset(g, , sizeof(g));
tot = -;
memset(du, , sizeof(du));
rt = ;
for (int i = ; i <= m; ++i)
{
int a, b;
scanf("%d%d", &a, &b);
++du[a];
if (du[a] > ) rt = a;
++du[b];
if (du[b] > ) rt = b;
ins(a, b);
ins(b, a);
}
cnt = ;//从根伸出去的链+环的数量
memset(col, , sizeof(col));
col[rt] = ;//访问标记
for (int i = g[rt]; i != -; i = r[i].next)
if (col[r[i].adj] == )
{
t0 = r[i].adj;//用于判环
d[cnt].circle = ;//是否在环中
d[cnt].len = ;//此链Or环的长度(可以想成是点的数量)
dfs(r[i].adj);
++cnt;
}
}

清北学堂模拟day6 兔子的更多相关文章

  1. 清北学堂模拟day6 圆桌游戏

    [问题描述] 有一种圆桌游戏是这样进行的:n个人围着圆桌坐成一圈,按顺时针顺序依次标号为1号至n号.对1<i<n的i来说,i号的左边是i+1号,右边是i-1号.1号的右边是n号,n号的左边 ...

  2. 清北学堂模拟day6 花

    [问题描述] 商店里出售n种不同品种的花.为了装饰桌面,你打算买m支花回家.你觉得放两支一样的花很难看,因此每种品种的花最多买1支.求总共有几种不同的买花的方案?答案可能很大,输出答案mod p的值. ...

  3. 清北学堂模拟赛day7 数字碰撞

    /* clj:水题别人都满分你不是你就完了,所以说水题一定要细心一点,有这么几个细节:①前导零的处理,全是零的时候要特判②换行要注意,不要多大一行,剩下就是水水的模拟了 */ #include< ...

  4. 清北学堂模拟赛d4t1 a

    分析:大模拟,没什么好说的.我在考场上犯了一个超级低级的错误:while (scanf("%s",s + 1)),导致了死循环,血的教训啊,以后要记住了. /* 1.没有发生改变, ...

  5. 清北学堂模拟赛day7 错排问题

    /* 考虑一下已经放回m本书的情况,已经有书的格子不要管他,考虑没有书的格子,不考虑错排有(n-m)!种,在逐步考虑有放回原来位置的情况,已经放出去和已经被占好的格子,不用考虑,剩下全都考虑,设t=x ...

  6. 清北学堂模拟赛day7 石子合并加强版

    /* 注意到合并三堆需要枚举两个端点,其实可以开一个数组记录合并两堆的结果,标程好像用了一个神奇的优化 */ #include<iostream> #include<cstdio&g ...

  7. 清北学堂模拟day4 捡金币

    [问题描述]小空正在玩一个叫做捡金币的游戏.游戏在一个被划分成 n行 n列的网格状场地中进行.每一个格子中都放着若干金币,并且金币的数量会随着时间而不断变化. 小空的任务就是在网格中移动,拾取尽量多的 ...

  8. 清北学堂模拟day4 传球接力

    [问题描述]n 个小朋友在玩传球. 小朋友们用 1 到 n 的正整数编号. 每个小朋友有一个固定的传球对象,第 i 个小朋友在接到球后会将球传给第 ai个小朋友, 并且第 i 个小朋友与第 ai个小朋 ...

  9. 清北学堂模拟day4 业务办理

    [问题描述]在银行柜台前,有 n 个顾客排队办理业务. 队伍中从前往后,第 i 位顾客办理业务需要ti 分钟时间. 一位顾客的等待时间定义为:队伍中在他之前的所有顾客和他自己的办理业务时间的总和.第 ...

随机推荐

  1. PHP Datatype Conversion Safety Risk、Floating Point Precision、Operator Security Risk、Safety Coding Principle

    catalog . 引言 . PHP operator introduction . 算术运算符 . 赋值运算符 . 位运算符 . 执行运算符 . 递增/递减运算符 . 数组运算符 . 类型运算符 . ...

  2. IEnumerable 遍历用法

    咋一看到IEnumerable这个接口,我们可能会觉得很神奇,在一般的编程时,基本上我们是想不到去用它的,可是,俗话说得好,存在便是道理,那么,它对我们来说,能够带来哪些奇妙的事情呢? 要想弄懂它,我 ...

  3. List多对多的查询应用

    /** * @param param * @author mercy 查询主副产品(主副产品是多对多的关系) * @return */ public String queryProductSpecAt ...

  4. ARPSpoofing教程(四) - 捕获并分析数据包

    本程序的主要目标是展示如何解析所捕获的数据包的协议首部. 这个程序可以称为UDPdump,打印一些网络上传输的UDP数据的信息. 1: #include"pcap.h" 2: ty ...

  5. php代码加密

    <?php function encode_file_contents($filename) { $type=strtolower(substr(strrchr($filename,'.'),1 ...

  6. 利用Objective-C运行时hook函数的三种方法

    版权声明:转载请注明出处:http://blog.csdn.net/hursing 方法一,hook已有公开头文件的类: 首先写一个Utility函数: #import <objc/runtim ...

  7. 开发板ping不通主机和虚拟机的看过来(转载)!

    前几天在做uboot下用tftp下载文件到开发板的实验时,为了能解决开发板ping不通主机和虚拟机的问题,可谓绞尽脑汁,正所谓久病成医,虽然为了这一小问题废了我那么长时间,但我在解决问题的同时也学到了 ...

  8. 基本药目录sop

    http://db.yaozh.com/basicdir 基本药物 编辑 "基本药物"的概念, 由世界卫生组织于1977年提出,指的是能够满足基本医疗卫生需求,剂型适宜.保证供应. ...

  9. js正则匹配浮点数或整数

    var pos='point(12.4 -45.423453)';var re = /([+]\d+[.]\d+|[-]\d+[.]\d+|\d+[.]\d+|[+]\d+|[-]\d+|\d+)/i ...

  10. linux配置oracle11G监听及本地网络服务 及 数据库建库

    配置监听及本地网络服务 在oracle用户的图形界面oracle用户中,新开启一个终端,输入命令netca 会弹出如下界面. 数据库建库 在oracle用户的图形界面oracle用户中,新开启一个终端 ...