• 【NOIp 2003】【树结构·搜索】传染病防治


    描述

    研究表明,这种传染病的传播具有两种很特殊的性质;
    第一是它的传播途径是树型的,一个人X只可能被某个特定的人Y感染,只要Y不
    得病,或者是XY之间的传播途径被切断,则X就不会得病。
    第二是,这种疾病的传播有周期性,在一个疾病传播周期之内,传染病将只会感染一
    代患者,而不会再传播给下一代。
    这些性质大大减轻了蓬莱国疾病防控的压力,并且他们已经得到了国内部分易感人群
    的潜在传播途径图(一棵树)。但是,麻烦还没有结束。由于蓬莱国疾控中心人手不够,同时也缺乏强大的技术,以致他们在一个疾病传播周期内,只能设法切断一条传播途径,而没有被控制的传播途径就会引起更多的易感人群被感染(也就是与当前已经被感染的人有传播途径相连,且连接途径没有被切断的人群)。当不可能有健康人被感染时,疾病就中止传播。所以,蓬莱国疾控中心要制定出一个切断传播途径的顺序,以使尽量少的人被感染。你的程序要针对给定的树,找出合适的切断顺序。

    格式

    输入格式

    输入格式的第一行是两个整数n(1≤n≤300)和p。接下来p行,每一行有两个整数i
    和j,表示节点i和j间有边相连(意即,第i人和第j人之间有传播途径相连)。其中节点
    1是已经被感染的患者。

    输出格式

    只有一行,输出总共被感染的人数。

    代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    struct node{
        int num,dep,sumSon,numSon;//节点编号,深度,子树节点数和,子节点个数 
        int Son[310];
    }t[400];
    
    int n,p,ans=10000000,maxdep=0;
    bool g[400][400],vis[400];
    vector<int> d[400];
    
    int build_tree(int rt,int dep){
        int sumSon=1,numSon=0;
        vis[rt]=1;
        t[rt].dep=dep; t[rt].num=rt;
        for(int i=1;i<=n;i++){
            if(!vis[i]&&g[rt][i]){
                sumSon+=build_tree(i,dep+1);
                numSon++;
                t[rt].Son[numSon]=i;
            }
        }
        t[rt].numSon=numSon; t[rt].sumSon=sumSon; 
        return sumSon;//sumSon是包括自己在内的子树大小 
    }
    
    void find_dep_num(){
        for(int i=1;i<=n;i++) {
            maxdep=max(maxdep,t[i].dep);
            d[t[i].dep].push_back(t[i].num);
        }
        return;
    }
    
    void search(int dep,int val){
        ans=min(ans,val);
        if(dep>maxdep) return;
        int end=d[dep].size();
        for(int i=0;i<end;i++){
            int cur=d[dep][i];
            if(vis[cur]){
                for(int j=1;j<=t[cur].numSon;j++){
                    vis[t[cur].Son[j]]=1;
                }
            }
        }
        for(int i=0;i<end;i++){
            int cur=d[dep][i];
            if(!vis[cur]){
                for(int j=1;j<=t[cur].numSon;j++){
                    vis[t[cur].Son[j]]=1;
                    search(dep+1,val-t[t[cur].Son[j]].sumSon);
                }
                for(int j=1;j<=t[cur].numSon;j++){
                    vis[t[cur].Son[j]]=0;
                }
            }
        }
        for(int i=0;i<end;i++){
            int cur=d[dep][i];
            if(vis[cur]){
                for(int j=1;j<=t[cur].numSon;j++){
                    vis[t[cur].Son[j]]=0;
                }
            }
        }
    }
    
    int main(){
        //freopen("in.txt","r",stdin);
        memset(g,0,sizeof(g));
        memset(vis,0,sizeof(vis));
        scanf("%d%d",&n,&p);
        for(int i=1;i<=p;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            g[a][b]=1; g[b][a]=1;
        }
        build_tree(1,0);
        find_dep_num();
        /*for(int i=1;i<=maxdep;i++){
            printf("dep %d: ",i);
            for(int j=0;j<d[i].size();j++){
                printf("%d ",d[i][j]);
            }
            puts("
    ");
        }*/
        memset(vis,0,sizeof(vis));
        search(0,t[1].sumSon);
        printf("%d",ans);
        return 0;
    } 
  • 相关阅读:
    DevOps、CI、CD都是什么鬼?
    卧槽!华为《Linux中文手册》火了,完整版 PDF 开放下载!
    MongoDB 常用运维实践总结
    谈谈变更过程中的运维意识
    Ping原理详解
    为什么Redis要比Memcached更火?
    一篇文章教你搞懂日志采集利器 Filebeat
    工程师姓什么很重要!别再叫我“X工”!!!
    这些 Shell 分析服务器日志命令集锦,收藏好
    Linux下找出吃内存的方法总结
  • 原文地址:https://www.cnblogs.com/leotan0321/p/6081385.html
Copyright © 2020-2023  润新知