3兔子

【问题描述】

在一片草原上有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

一遇到这类题就很晕

思路:

  有一个点入度大于二,这是一个突破点。我只要把这个点的避难所找到,剩下的就是链或者是环了。

  但是即使是即使给我一堆链和环,也无法直接找出最后一只到达避难所的兔子花费的最短时间,

  所以只能二分一个时间,把问题转化成对于这个时间是否符合题意(不一定最小)的判定性问题。

做法出来了:二分答案,先处理入度大于2的点,然后处理链和环最少需要多少个避难所。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 1000010
#define ll long long
using namespace std;
#define INF 0x7ffffff
int n,m,k;
int h[1501],nex[3100],to[3100],cnt,du[1501];
void add(int x,int y)    {to[++cnt]=y;nex[cnt]=h[x];h[x]=cnt;}
int root,size;
bool vis[1501][10];//

void dfs(int now,int pre,int dis,int op)
{
    vis[now][op]=1;size++;
    if(!dis)    return ;
    for(int i=h[now];i;i=nex[i])
    if((to[i]!=pre)&&(!vis[to[i]][op])&&((op!=2)||(!vis[to[i]][1])))
        dfs(to[i],now,dis-1,op);
}
int main()
{
    freopen("rabbit.in","r",stdin);
    freopen("rabbit.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    int a,b;
    while(m--)
    {
        scanf("%d%d",&a,&b);
        add(a,b);add(b,a);
        du[a]++,du[b]++;
    }
    root=1;
    for(int i=1;i<=n;i++)
    if(du[i]>=3)
    {
        root=i;
        break;
    }
    int l=0,r=n,mid,tmp,put;
    while(l<r)
    {
        mid=(l+r)>>1;
        for(int i=1;i<=n;i++)    vis[i][0]=0;
        dfs(root,0,mid,0);
        put=INF;
        for(int i=1;i<=n;i++)
        if(vis[i][0])
        {
            for(int j=1;j<=n;j++) vis[j][1]=vis[j][2]=0;

            dfs(i,0,mid,1);
            tmp=1;

            for(int j=1;j<=n;j++)
            if((!vis[j][1])&&(!vis[j][2]))
            {
                size=0;
                dfs(j,0,INF,2);
                tmp+=(size-1)/(2*mid+1)+1;
            }

            put=min(put,tmp);
        }
        if(put<=k)    r=mid;
        else l=mid+1;
    }
    printf("%d",l);
    return 0;
} 

小数据:

 输入:

  4 4 3

  1 2

  2 3

  1 4

  3 4

输出: 1

  

  

时间: 2024-10-26 06:55:20

3兔子的相关文章

递归函数____斐波拉契数列____出生2个月后小兔子可以生小小兔子

2017-09-17 22:41:44 递归     ____函数自己调用自己,又可以理解为自己的事情自己做.    如果觉得难以理解,可以把理解成这个函数调用了一个函数,只是这个函数和自己长得一模一样. ---------------------------------------------------------------------------------------     拿一对刚出生的小兔子编故事.     假设,一对刚出生的小兔子,第一个月没有繁殖能力,两个月后生下一对兔子.

bzoj1001 [BeiJing2006]狼抓兔子

1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 23723  Solved: 5981[Submit][Status][Discuss] Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M

js算法集合(二) javascript实现斐波那契数列 (兔子数列) Javascript实现杨辉三角

js算法集合(二)  斐波那契数列.杨辉三角 ★ 上一次我跟大家分享一下做水仙花数的算法的思路,并对其扩展到自幂数的算法,这次,我们来对斐波那契数列和杨辉三角进行研究,来加深对Javascript的理解. 一.Javascript实现斐波那契数列 ①要用Javascript实现斐波那契数列,我们首先要了解什么是斐波那契数列:斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为

养兔子Fibo函数优化

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> /* var cache = (function createCache() { var data = []; return function c

【BZOJ 1001】[BeiJing2006]狼抓兔子

Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路是

5.16 兔子生兔子,日期时间练习

namespace ConsoleApplication8 { class Program { static void Main(string[] args) { #region // //有一对幼兔,幼兔一个月后长成小兔,小兔一个月后长成成兔.并生下一对幼兔, //// 问几年后,有多少对幼兔,多少对小兔,多少对成兔,兔子总数是多少? // // 成兔每月生一对幼兔. // Console.WriteLine("请输入月份"); // int MM = int.Parse(Conso

[BZOJ1001] [Beijing2006] 狼抓兔子 (最短路)

Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路是

一对幼兔一个月长成小兔,再过一月长成成兔并生下幼兔,问24个月之后有多少对兔子,成兔每个月都会生下一对幼兔

int a=1,b=0,c=0,sum = 0;//a 幼兔对数,b 小兔对数,c 成兔对数,sum 总对数 for (int i = 1; i <=24; i++) { if (i == 1) { a = 1; b = 0; c = 0; } else { c = b + c; b = a; a = c; } sum = a + b + c; Console.WriteLine(i+"个月后,一共有兔子" + sum + "对,其中幼兔" + a + &qu

兔子数量【转载】

package 兔子数量; /** * 兔子问题 * 斐波那契数列求值 *题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子, *小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? *1.程序分析: 兔子的规律为数列1,1,2,3,5,8,13,21.... */ public class rabbit { public static final int MONTH = 15; public static void main(String[] arg

【bzoi2006】【狼抓兔子】【最小割】

Description Source: Beijing2006 [BJOI2006] 八中OJ上本题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 如今小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比較在行的.并且如今的兔子还比較笨,它们仅仅有两个窝,如今你做为狼王,面对以下这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)&