• luoguP1041 传染病控制 x


    P1041 传染病控制

    题目背景

    近来,一种新的传染病肆虐全球。蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延。不幸的是,由于人们尚未完全认识这种传染病,难以准确判别病毒携带者,更没有研制出疫苗以保护易感人群。于是,蓬莱国的疾病控制中心决定采取切断传播途径的方法控制疾病传播。经过 WHO(世界卫生组织)以及全球各国科研部门的努力,这种新兴传染病的传播途径和控制方法已经研究清楚,剩下的任务就是由你协助蓬莱国疾控中心制定一个有效的控制办法。

    题目描述

    研究表明,这种传染病的传播具有两种很特殊的性质;

    第一是它的传播途径是树型的,一个人X只可能被某个特定的人Y感染,只要Y不得病,或者是XY之间的传播途径被切断,则X就不会得病。

    第二是,这种疾病的传播有周期性,在一个疾病传播周期之内,传染病将只会感染一代患者,而不会再传播给下一代。

    这些性质大大减轻了蓬莱国疾病防控的压力,并且他们已经得到了国内部分易感人群的潜在传播途径图(一棵树)。但是,麻烦还没有结束。由于蓬莱国疾控中心人手不够,同时也缺乏强大的技术,以致他们在一个疾病传播周期内,只能设法切断一条传播途径,而没有被控制的传播途径就会引起更多的易感人群被感染(也就是与当前已经被感染的人有传播途径相连,且连接途径没有被切断的人群)。当不可能有健康人被感染时,疾病就中止传播。所以,蓬莱国疾控中心要制定出一个切断传播途径的顺序,以使尽量少的人被感染。

    你的程序要针对给定的树,找出合适的切断顺序。

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

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

    思路:

      1.dfs

        首先连边,将小号指向大号,然后开始寻找每个点的深度(点1必须为1),接着开始进行dfs+最优性剪枝,如果不能够再感染他的子节点,就更新ans的值.

      2.据说这题贪心是可以过得.

      3.据说这题用树链剖分是可以做的.

      4.然而2+3我是不会做的

    坑点:

      一定要将ans赋值为较大的数!!!因为更新答案的时候是取min

    上代码:

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    const int M = 23333;
    const int INF = 0x7fffffff;
    int n,p,ans=INF;
    int head[M],tot;
    bool ill[M];
    int deeps[M];
    
    struct B{
        int next,to;
    }e[M];
    
    void add(int u,int v)
    {
        e[++tot].to=v;
        e[tot].next=head[u];
        head[u]=tot;
    }
    
    void finds(int u)
    {
        int v;
        for(int i=head[u];i;i=e[i].next)
        {
            v=e[i].to;
            deeps[v]=deeps[u]+1;
            finds(v);
        }
        return;
    }
    
    void DFS(int deep,int num)
    {
        if(num>=ans)///最优性剪枝 
            return;
        bool flag=false;
        int v;
    
        for(int i=1;i<=n;i++)
        {
            if(deeps[i]==deep && ill[i])
            {
                for(int j=head[i];j;j=e[j].next)
                {
                    v=e[j].to;
                    ill[v]=true;
                    flag=true;
                    ///还有儿子节点可以被感染 
                    num++;
                }
            }
        }
        num--;///因为当前节点已经被感染了,不能再感染一次
    
        for(int i=1;i<=n;i++)
        {
            if(deeps[i]==deep+1 && ill[i])///如果是当前节点的子节点
            {
                ill[i]=false;
                DFS(deep+1,num);
                ill[i]=true;
                ///回溯 
            }
        }
    
        ///回溯
        num++;
        for(int i=1;i<=n;i++)
        {
            if(deeps[i]==deep && ill[i])
            {
                for(int j=head[i];j;j=e[j].next)
                {
                    v=e[j].to;
                    ill[v]=false;
                    num--;
                }
            }
        }
        if(!flag)///如果不能够继续进行感染了 
        {
            ans=min(ans,num);
            ///更新答案 
            return;
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&p);
        for(int i=1,x,y;i<=p;i++)
        {
            scanf("%d%d",&x,&y);
            if(x>y) add(y,x);
            else add(x,y);
        }
        ///初始化1节点的状态 
        deeps[1]=1;///1的深度为1 
        ill[1]=true;///1被感染了
        finds(1);///寻找每个节点的深度 
        DFS(1,1);///寻找答案 
        printf("%d
    ",ans); 
        return 0;
    }

    End.

    如果运气好也是错,那我倒愿意错上加错!

    ❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀

  • 相关阅读:
    Windows服务器上Mysql为设置允许远程连接提示:not allowed to connect to this MySQL server
    Java中怎样遍历两个Date日期之间的每一天
    ElementUI中el-table设置指定列固定不动,不受滚动条影响
    APP测试时不可忽视搭建代理服务器抓包测试的必要性
    ctype库试运行
    django-grappelli 安装配置
    windows下django1.7 +python3.4.2搭建记录2
    windows下django1.7 +python3.4.2搭建记录1
    【2020-11-15】大心境并不能自动化解小结
    【2020-11-14】对自己责任心的煎熬考验
  • 原文地址:https://www.cnblogs.com/zxqxwnngztxx/p/7117089.html
Copyright © 2020-2023  润新知