• P1014 传染病控制 [搜索]


    传染病控制

    题目描述见链接 .


    color{grey}{最初想法}

    刚开始题意理解错, 认为是每个节点都可以切断自己的一颗子树 . WA code .

    每次传染病向下传递只会传递 11 层, 所以可以看做传染病按层推进,
    题意可以转化为: 每次切断一条通往下一层中一个子节点的路径, 以求最少的被传染人数 .

    然后现在的问题就是切断哪条路径,
    发现这个问题不能靠dpdp解决, 因为当切断一个子树的一条路径时, 与该子树根节点同层的节点就不能切断路径了, 换句话说, dpdp 会有后效性 .


    color{red}{正解部分}

    现在只剩下一个可行的方法了 ----- 搜索 .

    深度 为阶段进行搜索, 每次选择切断哪个儿子, 暴力 DFSDFS 即可 .


    color{red}{实现部分}

    DFSDFS 是否到了尽头不好判断, 进而直接统计被感染的人数不好统计, 于是考虑记录没被感染的人数,
    记录每个子树的大小 size[]size[], 在切断子树时在原有的大小 sumsum 上减去该子树大小, 更新答案即可 .

    sumsum 初值为 size[1]size[1] .

    #include<bits/stdc++.h>
    #define reg register
    #define pb push_back
    
    const int maxn = 305;
    
    int N;
    int p;
    int Ans;
    int num0;
    int F[maxn];
    int dep[maxn];
    int head[maxn];
    int size[maxn];
    
    bool vis[maxn];
    
    std::vector <int> A[maxn];
    
    struct Edge{ int nxt, to; } edge[maxn << 1];
    
    void Add(int from, int to){
            edge[++ num0] = (Edge){ head[from], to };
            head[from] = num0;
    }
    
    void DFS(int k, int fa){
            dep[k] = dep[fa] + 1, size[k] = 1, A[dep[k]].pb(k);
            for(reg int i = head[k]; i; i = edge[i].nxt){
                    int to = edge[i].to;
                    if(to == fa) continue ;
                    DFS(to, k); size[k] += size[to];
            }
    }
    
    void DFS_3(int k, int v){
            vis[k] = v;
            for(reg int i = head[k]; i; i = edge[i].nxt){
                    int to = edge[i].to;
                    if(dep[to] < dep[k]) continue ;
                    DFS_3(to, v);
            }
    }
    
    void DFS_2(int k, int sum){
            Ans = std::min(Ans, sum);
            int siz = A[k+1].size();
            for(reg int i = 0; i < siz; i ++){
                    int to = A[k+1][i];
                    if(vis[to]) continue ;
                    DFS_3(to, 1), DFS_2(k+1, sum-size[to]), DFS_3(to, 0);
            }
    }
    
    int main(){
            scanf("%d%d", &N, &p);
            for(reg int i = 1; i <= p; i ++){
                    int x, y;
                    scanf("%d%d", &x, &y);
                    Add(x, y), Add(y, x);
            }
            Ans = N + 1;
            DFS(1, 0); DFS_2(1, size[1]);
            printf("%d
    ", Ans);
            return 0;
    }
    

    好暴力啊…

  • 相关阅读:
    阿里云证书nginx无法访问带点的路径
    升级阿里云服务器文案
    html模板结合JS替换函数,生成新的记录
    企业使命、原景、战略、战略目标 详解
    Android之Handler用法总结【转】
    android activity的常用代码:关闭、传值、返回值、回调、网页、地图、短信、电话
    PHP十进制转36进制的函数
    [转]仓库管理必须知道的的50条重要知识
    [转]关于项目管理、软件开发的一些思考
    PHP5.5安装PHPRedis扩展
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822493.html
Copyright © 2020-2023  润新知