【问题描述】

在一片草原上有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. 贴一段shell代码

    好久没用shell了,呵呵,这个是当counter < 1000的时候,往tmp.sql里填这两个字符串,生成假数据. #!/usr/bin/env bash COUNTER= ]; do ec ...

  2. 数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树

    一.简述 二叉树的遍历主要是先序.中序.后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些.二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具! 此外,非递归所用的栈 ...

  3. Objective-C 中基于RunTime实现的反射

    一.反射 反射,一般表现在字符串和Class转换,字符串和内部方法转换,字符串和属性的转换(取值和赋值). 二.Objective-C中的反射 OC的反射是基于其Runtime实现的. 以执行某个函数 ...

  4. iOS @property的默认属性

    我是一个比较懒的人,很多情况下@property都不喜欢加属性…所以必须了解默认情况下哪些是已经有的,哪些在需要时是必须要加的. 原文链接:http://blog.sina.com.cn/s/blog ...

  5. CentOS编译安装nodejs

    1. 从node.js官网下载最新版的node.js安装包,node.tar.gz wget https://nodejs.org/dist/v4.3.1/node-v4.3.1.tar.gz    ...

  6. 【Beta版本】冲刺-Day5

    队伍:606notconnected 会议时间:12月13日 目录 一.行与思 二.站立式会议图片 三.燃尽图 四.代码Check-in 一.行与思 张斯巍(433) 今日进展:继续修改界面及图标设计 ...

  7. 【Alpha版本】冲刺-Day8

    队伍:606notconnected 会议时间:11月16日 会议总结 张斯巍(433) 今天安排:回收站界面设计 完成度:90% 明天计划:关注界面设计 遇到的问题:无 感想:有时候自己设计的队友说 ...

  8. vimium Keyboard Bindings

    Modifier keys are specified as `<c-x>`, `<m-x>`, and `<a-x>` for ctrl+x, meta+x, a ...

  9. JAVA 自定义状态码

    返回信息类(ResponseInfo): public class ResponseInfo { public static final String Status = "status&qu ...

  10. 从.o文件中提取指定开头依赖于外部接口的脚本

    nm -g audio_la-audio.o | grep " U " | awk '{ print $2}' | grep "^gst_"