zoukankan      html  css  js  c++  java
  • 洛谷 P3942 将军令 解题报告

    P3942 将军令

    题目描述

    又想起了四月。

    如果不是省选,大家大概不会这么轻易地分道扬镳吧? 只见一个又一个昔日的队友离开了机房。

    凭君莫话封侯事,一将功成万骨枯。

    梦里,小(F)成了一个给将军送密信的信使。

    现在,有两封关乎国家生死的密信需要送到前线大将军帐下,路途凶险,时间紧迫。小(F)不因为自己的祸福而避趋之,勇敢地承担了这个任务。

    不过,小(F)实在是太粗心了,他一不小心把两封密信中的一封给弄掉了。

    (F)偷偷打开了剩下的那封密信。他 发现一副十分详细的地图,以及几句批文——原来 这是战场周围的情报地图。他仔细看后发现,在这张地图上标记了(n)个从 1 到(n)标号的 驿站,(n−1)条长度为1里的小道,每条小道双向连接两个不同的驿站,并且驿站之间可以 通过小道两两可达。

    (F)仔细辨认着上面的批注,突然明白了丢失的信的内容了。原来,每个驿站都可以驻 扎一个小队,每个小队可以控制距离不超过(k)里的驿站。如果有驿站没被控制,就容易产 生危险——因此这种情况应该完全避免。而那封丢失的密信里,就装着朝廷数学重臣留下的 精妙的排布方案,也就是用了最少的小队来控制所有驿站。

    (F)知道,如果能计算出最优方案的话,也许他就能够将功赎过,免于死罪。他找到了 你,你能帮帮他吗? 当然,小(F) 在等待你的支援的过程中,也许已经从图上观察出了一些可能会比较有用的 性质,他会通过一种特殊的方式告诉你。

    输入输出格式

    输入格式:

    从标准输入中读入数据。

    输入第 1 行一个正整数(n,k,t),代表驿站数,一支小队能够控制的最远距离,以及特殊性质所代表的编号。关于特殊性质请参照数据范围。

    输入第 2 行至第(n)行,每行两个正整数(u_i,v_i),表示在(u_i)(v_i)间,有一条长度为 一里的小道。

    输出格式:

    输出到标准输出中。

    输出一行,为最优方案下需要的小队数。

    说明:

    子任务会给出部分测试数据的特点。如果你在解决题目中遇到了困难,可以尝试只解 决一部分测试数据。

    关于 t 的含义如下: t = 0:该测试点没有额外的特殊性质; t = 1:保证最多 8 个点的所连接的小道超过 1 条; t = 2:保证所有点到 1 号点的距离不超过 2。

    每个测试点的数据规模及特点如下表


    贪心策略:自下向上做,当一个点不得不需要照看的时候,进行照看。

    正确性:保证了每个照看点尽可能的高,也就覆盖的更多。即由最优推最优。

    实现:在(dfs)过程中,每次从子节点接受一个值(x)

    (x>0)时,代表当前节点存在至少一个比它低(x-1)的节点需要照看

    (x<=0)时,代表当前节点还可以覆盖离它距离不超过(-x)的点

    对每个节点找到最大正值和最小非负值,看看能否用负的照看正的。

    复杂度:(O(n))


    Code:

    #include <cstdio>
    const int N=100010;
    int head[N],to[N<<1],Next[N<<1],cnt;
    void add(int u,int v)
    {
        to[++cnt]=v;Next[cnt]=head[u];head[u]=cnt;
    }
    int n,used[N],ans=0,k,t;
    void init()
    {
        scanf("%d%d%d",&n,&k,&t);
        int u,v;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u);
        }
    }
    int dfs(int now)
    {
        int mx=1,mi=1;
        used[now]=1;
        for(int i=head[now];i;i=Next[i])
        {
            int v=to[i];
            if(!used[v])
            {
                int x=dfs(v);
                if(x>0) mx=mx>x?mx:x;
                else  mi=mi<x?mi:x;
            }
        }
        if(-mi>=mx-1) return mi+1;
        if(mx<=k) return mx+1;
        ans++;
        return -k+1;
    }
    int main()
    {
        //freopen("data.in","r",stdin);
        //freopen("wr.out","w",stdout);
        init();
        if(k&&dfs(1)>k) ans++;
        printf("%d
    ",ans);
        return 0;
    }
    

    2018.7.11

  • 相关阅读:
    C# 以GZip解压缩
    C# 获取时间戳(支持毫秒)
    C#中 DateTime 转 DateTimeOffset
    C# WPF中 SecureString 转 String
    C# 根据文件头判断文件类型
    C#中 MD5 32位加密
    C#中 Stream转为byte[]
    C#中byte[]转BitmapImage
    sql按天分组
    eclispe报错PermGen space
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9297154.html
Copyright © 2011-2022 走看看