📜  门| GATE CS Mock 2018 |问题 22(1)

📅  最后修改于: 2023-12-03 15:42:13.403000             🧑  作者: Mango

门 | GATE CS Mock 2018 | 问题 22

这是GATE CS模拟考试2018年的第22个问题。

题目描述

考虑一个带有n个节点的无向图,节点编号为1到n。 每个节点都带有一个数字,表示在该节点上放置锁需要的数量。 假设可以同时锁定每个节点,如果它的相邻节点都被锁定,那么该节点是被锁定的。

例如,图中的节点A,B,C都有一个锁,节点D需要在这三个节点上放置锁才能被锁定。

A----B
 \  /
  \/
  C
   \
    \
     D

已知每个节点的数字,现在需要计算在该图上放置锁需要的最小数量。可以假设有足够数量的锁。

输入格式

第一行包含一个整数n,表示节点的数量。 接下来的n行中,第i行包含一个整数ai,表示节点i上的锁的数量。

接下来的n行中,表示节点之间的连接。每行包含两个整数u和v,表示节点u和节点v之间有连接。 输入保证给定的连接构成一颗树。

输出格式

输出一个整数,表示在该图上放置锁需要的最小数量。

示例

输入:

4
1
1
1
1
1 2
2 3
3 4

输出:

2
解题思路

这个问题可以使用动态规划来解决。假设我们已经计算了节点1到i-1的最小锁的数量。现在考虑节点i的锁。我们可以进行两种操作:

  1. 放置锁。在放置锁之前,我们需要确保节点1到i-1已经被锁住。这可以通过检查节点i的相邻节点是否被锁住来实现。

  2. 不放置锁。在这种情况下,我们需要确保节点1到i-1已经被锁住。

使用动态规划的话,我们可以定义dp[i]表示放置节点1到i的最小锁的数量。这样,可以通过迭代式计算得到最小锁的数量。

迭代式: dp[i] = min(dp[i-1]+a[i], dp[i-2]+b[i]),其中a[i]表示放置节点i的锁的数量,b[i]表示不放置节点i的锁的数量。如果该节点没有相邻的节点,则b[i]等于dp[i-1]。

参考实现

下面是基于Python的参考实现:

def minimum_locks(n, a, edges):
    graph = [[] for i in range(n+1)]
    for u, v in edges:
        graph[u].append(v)
        graph[v].append(u)

    done = [False] * (n+1)
    dp = [0] * (n+1)
    stack = [1]

    while stack:
        node = stack[-1]
        if not done[node]:
            done[node] = True
            child_dp = []
            child_count = 0
            for child in graph[node]:
                if not done[child]:
                    stack.append(child)
            continue
        
        stack.pop()
        if not child_dp:
            dp[node] = a[node-1]
        else:
            dp[node] = min(child_dp) + a[node-1] + child_count
        if node > 1:
            child_dp.append(dp[node-1])
            child_count += 1
            if len(child_dp) == 2:
                child_dp.sort()
                dp[node] = min(dp[node], child_dp[0]+child_dp[1]+child_count)

    return dp[n]

该函数minimum_locks接受三个参数:

  • n:节点数量
  • a:一个列表,包含每个节点上锁的数量。
  • edges:一个列表,表示图中节点的边。每个元素是一个表示边的元组(u, v),其中u和v分别是边的两个端点的编号。

该函数使用一个栈来迭代图的节点。栈中维护了待处理的节点编号。在处理一个节点时,首先将该节点的未处理的子节点入栈,然后在需要时弹出该节点,并计算出相邻节点的dp值。请注意,该算法按顺序处理节点,并使用栈来跟踪适当的处理顺序(也可以使用队列进行广度优先搜索)。

在提交这个问题时,您可能需要基于给定的输入格式进行微调。