控制传染病-蓝桥杯-python解法

题目描述

解题思路

由题意可知这是一个树型传染图,其中每一次只能感染一代也就是只能传递一层,而每一次的防控措施也只能切断一条,也就是每次传播只能切断一条两个结点的边。

 这是由题给条件画出的传播图,初始状态下只有结点1被感染,第一次传播切断1和3之间的联系,感染了结点2,第二次传播切断结点2和结点4之间的联系感染了结点5,传播结束一共感染力1,2,5一共3个结点。所以我们只用依次递归计算每个结点最小的感染人数(深度优先计算),其中每一次切断一条路径就是把下一层的人数减一。

代码

根据输入创建树,也就是深度优先的邻接表

    n,p=map(int,input().split())
    linkedlist=[[] for _ in range(n+1)]
    for _ in range(p):
        x,y=map(int,input().split())
        linkedlist[x].append(y)
        linkedlist[y].append(x)
    #linkedlist:[[], [2, 3], [1, 4, 5], [1, 6, 7], [2], [2], [3], [3]]
    tree=[[] for _ in range(n+1)]
    def createTree(root):
        if len(linkedlist[root])!=0:
            tree[root]=linkedlist[root]
            for x in linkedlist[root]:
                linkedlist[x].remove(root)
                createTree(x)
    createTree(1)
    #tree:[[], [2, 3], [4, 5], [6, 7], [], [], [], []]

其中tree就是我们构建的树,tree[1]就表示以1为父节点连接了2,3两个子节点。

深度优先遍历

# 输入当前层结点和当前感染人数,计算从下一层开始的被感染的最少人数并返回人数
bestresult = 300
def dfs(currentlayer, currentcount):
    global tree, bestresult
    nextlayer = []
    for x in currentlayer:
        nextlayer += tree[x]
    minnum = 300
    # 到达叶子结点,更新bestresult
    if nextlayer ==[]:
        if currentcount<bestresult:
            bestresult = currentcount
        return 0
    # 若感染人数大于bestresult则剪枝
    elif currentcount + len(nextlayer)-1<=bestresult:
        for i,x in enumerate(nextlayer):
            del nextlayer[i]
            nextnum = dfs(nextlayer, currentcount + len(nextlayer)-1)
            if minnum>nextnum:
                minnum = nextnum
            nextlayer.insert(i,x)
        #遍历完一颗子树,求得最小的感染数在加上下一层结点的数目减一就获得该父节点最小感染数
        return len(nextlayer)-1+minnum
    # 若大于则直接返回300(表示剪枝)
    else:
        return 300


#最后加的1是加上原本就被感染的根节点
print(dfs([1], 1)+1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值