zoukankan      html  css  js  c++  java
  • [洛谷P3942]将军令

    题目大意:有n个驿站形成一棵树。一支小队在某个驿站驻扎时,可以控制与这个驿站距离不超过k的所有驿站(每条边长度算1)。问至少需要驻扎多少小队?

    解题思路:贪心。要控制所有驿站,我们从最深的节点开始考虑。

    要使一支小队控制到这个节点,又要让它贡献尽可能多,我们应该让它驻扎在当前节点的第k个祖先的节点上。

    然后把所有已经被控制的节点打上标记。

    接着从剩下的、没被打上标记的最深的节点考虑,继续如上方法贪心即可。

    打标记的过程dfs一遍即可。

    最后驻扎了几支小队,答案就是多少。

    注意当一个节点没有第k个祖先(即它的某个祖先是根节点且不为第k个祖先),则直接让其驻扎在根节点上。

    C++ Code:

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,k,head[100005],cnt,fa[100005];
    bool vis[100005];
    struct edge{
        int to,nxt;
    }e[200010];
    struct Deep{
        int s,num;
        bool operator <(const Deep& rhs)const{return s>rhs.s;}
    }dep[100005];
    inline int readint(){
        char c=getchar();
        for(;!isdigit(c);c=getchar());
        int d=0;
        for(;isdigit(c);c=getchar())
        d=(d<<3)+(d<<1)+(c^'0');
        return d;
    }
    void dfs(int now){
        for(int i=head[now];i;i=e[i].nxt)
        if(e[i].to!=fa[now]){
            fa[e[i].to]=now;
            dep[e[i].to]=(Deep){dep[now].s+1,e[i].to};
            dfs(e[i].to);
        }
    }
    void fg(int now,int p,int pre){
        vis[now]=true;
        if(k!=p++)
        for(int i=head[now];i;i=e[i].nxt)
        if(e[i].to!=pre)
        fg(e[i].to,p,now);
    }
    int main(){
        cnt=0;
        memset(dep,0,sizeof dep);
        memset(head,0,sizeof head);
        n=readint(),k=readint();readint();
        for(int i=1;i<n;++i){
            int u=readint(),v=readint();
            e[++cnt]=(edge){v,head[u]};
            head[u]=cnt;
            e[++cnt]=(edge){u,head[v]};
            head[v]=cnt;
        }
        fa[1]=1;
        dep[1]=(Deep){1,1};
        dfs(1);
        sort(dep+1,dep+n+1);
        memset(vis,0,sizeof vis);
        int ans=0;
        for(int i=1;i<=n;++i)
        if(!vis[dep[i].num]){
            int grf=dep[i].num;
            for(int j=1;j<=k;++j)grf=fa[grf];
            fg(grf,0,grf);
            ++ans;
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Docker入门系列4:命令行小结
    Docker入门系列3:使用
    Docker入门系列2 安装
    Docker入门系列1:简介
    在VMware下安装CentOS系列1:配置VMware
    bugzilla 系列1安装
    查看SELinux状态并关闭SELinux
    Qt 编程指南 5 丰富文本编辑控件
    Qt 编程指南 4 单行编辑控件
    Qt 编程指南 4 按钮2 打开网页和文件夹
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7776947.html
Copyright © 2011-2022 走看看