zoukankan      html  css  js  c++  java
  • P3942 将军令

    题目描述

    又想起了四月。

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

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

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

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

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

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

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

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

    输入输出格式

    输入格式:

    从标准输入中读入数据。

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

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

    输出格式:

    输出到标准输出中。

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

    输入输出样例

    输入样例#1: 
    4 1 0 
    1 2 
    1 3 
    1 4
    输出样例#1: 
    1 
     
    输入样例#2: 
    6 1 0 
    1 2 
    1 3 
    1 4 
    4 5 
    4 6
    输出样例#2: 
    2 
    

    说明

    【样例 1 说明】

    如图。由于一号节点到周围的点距离均是 1,因此可以控制所有驿站。

    【样例 2 说明】

    如图,和样例 1 类似。

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

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

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

    代码

    贪心

    每次从深度最大的节点开始覆盖距离为k的祖先

    找祖先可以直接暴力,如果k再大一点。

    可以考虑倍增,当然这题没必要

    #include<bits/stdc++.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int maxn=1e5+10;
    int head[maxn],dis[maxn];
    int s[maxn];
    int inq[maxn],vis[maxn],fa[maxn];
    int size=0,tot=0;
    struct edge
    {
        int to,next;
    }e[maxn<<1];
    int ans=0;
    int n,k;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return x*f;
    }
    void addedge(int u,int v)
    {
        e[++size].to=v;e[size].next=head[u];head[u]=size;
    }
    void bfs(int u)
    {
        queue<int>q;
        q.push(u);
        s[++tot]=u;
        inq[u]=1;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u];i;i=e[i].next)
            { 
            int to=e[i].to;
            if(inq[to])continue;
            dis[to]=dis[u]+1;
            if(!inq[to])
            q.push(to),fa[to]=u,s[++tot]=to,inq[to]=1;
            }
        }
    
    }
    void dfs(int u,int fa,int d)
    {
        if(d>k)return;
        vis[u]=1;
        for(int i=head[u];i;i=e[i].next)
        {
            int to=e[i].to;
            if(to==fa)continue;
            dfs(to,u,d+1);
        }
    }
    
    int main()
    {
        memset(dis,-inf,sizeof(dis));
        n=read(),k=read(),read();
        for(int i=2;i<=n;i++)
        {
            int u=read(),v=read();
            addedge(u,v);addedge(v,u);
        }
        bfs(1);
        for(int i=tot;i;i--)
        {
            int x=s[i];
            if(vis[x])continue;
            ans++;
            for(int i=1;i<=k;i++)
            x=fa[x];
            dfs(x,0,0);
        }
        printf("%d",ans);
        return 0;
    } 
    View Code
  • 相关阅读:
    TCP/IP报文 三次握手 四次挥手
    socket 编程
    出现线程死锁的几种情况
    类模板的写法
    【HTTP】boundary 中一个 = 导致HTTP上传文件失败
    【时间戳】 年月日 转换为时间戳
    【CSV文件】CSV文件内容读取
    std::string 的方法c_str() 和 data() 有什么区别
    [转载] C++ STL中判断list为空,size()==0和empty()有什么区别
    【SQL】glob 和 like 的区别
  • 原文地址:https://www.cnblogs.com/DriverBen/p/11002489.html
Copyright © 2011-2022 走看看