【蓝桥杯】雪地工程核弹引爆控制器最小数量计算

问题描述

危机纪元 2211 年,由罗辑领导的雪地工程正式进入部署,雪地工程中布置了大量的核弹,整个工程由信号中转站和起爆装置构成,形成了一棵具有 nn 个点 n−1n−1 条边的有根树,11 号点为根节点,树边为 (ui,vi)(ui​,vi​) 。

起爆装置为度为 11 并且不是根的节点,其余节点为信号中转站,预先在 mm 个起爆装置上面布置有核弹,为了引爆核弹,会在 11 号节点施加一个引爆信号,在信号中转站上,该信号会随机向某一个子节点传输,为了避免核弹不被引爆,你可以在信号中转站上面安装控制器,使得引爆信号只会往指定的子节点传输,为了减少开销,你能帮帮罗辑计算最少需要安装的控制器数量吗?

输入格式

第 11 行包含一个正整数 nn(2≤ n ≤ 1052≤ n ≤ 105),表示树点的数量。

第 2∼n+12∼n+1 行每行包含 22 个正整数 ui,viui​,vi​(1≤ui,vi≤n1≤ui​,vi​≤n),分别表示树边的两个端点。

接下来 11 行包含一个正整数 mm (1≤ m ≤1≤ m ≤ 叶子数量) ,表示含有核弹的起爆装置的数量。

再接下来 11 行包含 mm 个整数 , 表示具有核弹起爆装置的节点编号。

输出格式

输出一个数字,表示需要放置的最小控制器数量。

样例输入

5
1 2 
1 3
1 4
2 5
2 
4 5

样例输出

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<vector<int>> adj(n + 1); // 邻接表
    for (int i = 0; i < n - 1; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    // 构建树结构,确定父子关系
    vector<int> parent(n + 1, 0);
    vector<vector<int>> children(n + 1);
    queue<int> q;
    vector<bool> visited(n + 1, false);
    q.push(1);
    visited[1] = true;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int v : adj[u]) {
            if (!visited[v]) {
                visited[v] = true;
                parent[v] = u;
                children[u].push_back(v);
                q.push(v);
            }
        }
    }

    int m;
    cin >> m;
    unordered_set<int> bomb_set;
    for (int i = 0; i < m; ++i) {
        int b;
        cin >> b;
        bomb_set.insert(b);
    }

    vector<bool> has_bomb(n + 1, false);
    for (int b : bomb_set) has_bomb[b] = true; // 标记核弹节点

    // 后序遍历标记所有包含核弹的子树
    stack<pair<int, bool>> st;
    st.push({1, false});
    while (!st.empty()) {
        auto [u, processed] = st.top();
        st.pop();
        if (!processed) {
            st.push({u, true});
            // 逆序入栈以保证子节点按顺序处理
            for (auto it = children[u].rbegin(); it != children[u].rend(); ++it)
                st.push({*it, false});
        } else {
            for (int v : children[u]) {
                if (has_bomb[v]) {
                    has_bomb[u] = true;
                    break; // 只要有一个子节点有炸弹,父节点即标记
                }
            }
        }
    }

    int ans = 0;
    for (int u = 1; u <= n; ++u) {
        // 判断是否为信号中转站:根节点或非叶子非根节点
        bool is_station = (u == 1) || (!children[u].empty());
        if (is_station) {
            int cnt = 0;
            for (int v : children[u]) {
                if (has_bomb[v]) cnt++;
            }
            ans += max(0, cnt - 1); // 需要控制器数为 cnt-1
        }
    }
    cout << ans << endl;
    return 0;
}

运行限制

语言最大运行时间最大运行内存
C++1s256M
C1s256M
Java2s256M
Python33s256M
PyPy33s256M
Go3s256M
JavaScript3s256M

代码思路解析

  1. 输入处理与树构建
    通过邻接表存储树结构,并用BFS确定父子关系,构建每个节点的子节点列表。

  2. 核弹标记
    标记所有含有核弹的叶子节点。

  3. 后序遍历标记子树
    从叶子节点向上回溯,标记每个节点的子树是否包含核弹。若某节点的子节点子树包含核弹,则该节点也被标记。

  4. 统计控制器数量
    遍历每个信号中转站节点,统计其子节点中包含核弹的数目。若数目超过1,则需在该节点安装(数目-1)个控制器,确保信号正确传输。

关键点

  • 信号中转站判断:根节点或非叶子节点。

  • 后序遍历更新子树标记:确保父节点正确反映子树的核弹状态。

  • 控制器计算:每个中转站需要控制器数为其包含核弹子节点数减一,确保最少干预。

 

题目详细解析

我们用一个具体例子理解题目:

样例输入

5
1 2 
1 3
1 4
2 5
2 
4 5 

关键逻辑

  1. 信号传播规则

    • 中转站(非叶子非根节点)默认随机选择一个子节点。

    • 安装控制器后,中转站可以指定信号传递方向。

  2. 核心观察

    • 如果某个中转站的多个子节点的子树包含核弹,必须强制信号走向这些子节点。

    • 控制器的作用是减少选择的不确定性,确保覆盖所有核弹。

  3. 解决方案

    • 统计每个中转站节点需要引导的子节点数量。

    • 若某中转站有 k 个子节点的子树含核弹,则需 k-1 个控制器。

代码分步解析

1. 邻接表构建与树的遍历

邻接表是树的标准存储方式,每个节点存储其直接连接的节点:

vector<vector<int>> adj(n + 1);
for (int i = 0; i < n - 1; ++i) {
    int u, v;
    cin >> u >> v;
    adj[u].push_back(v);
    adj[v].push_back(u);
}

通过BFS构建树的父子关系:

queue<int> q;
q.push(1);
visited[1] = true;
while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int v : adj[u]) {
        if (!visited[v]) {
            visited[v] = true;
            parent[v] = u;
            children[u].push_back(v); // 建立子节点列表
            q.push(v);
        }
    }
}
2. 后序遍历标记子树

通过后序遍历标记每个节点的子树是否含核弹:

stack<pair<int, bool>> st;
st.push({1, false});
while (!st.empty()) {
    auto [u, processed] = st.top();
    st.pop();
    if (!processed) {
        st.push({u, true});
        // 逆序入栈以保证处理顺序
        for (auto it = children[u].rbegin(); it != children[u].rend(); ++it)
            st.push({*it, false});
    } else {
        for (int v : children[u]) {
            if (has_bomb[v]) {
                has_bomb[u] = true; // 子节点有核弹则标记
                break;
            }
        }
    }
}

例如,节点5的 has_bomb 为真,其父节点2的 has_bomb 也会被标记为真。

3. 统计控制器数量

遍历所有中转站节点,计算需要控制器数量:

int ans = 0;
for (int u = 1; u <= n; ++u) {
    // 判断是否为中转站
    bool is_station = (u == 1) || (!children[u].empty());
    if (is_station) {
        int cnt = 0;
        for (int v : children[u]) {
            if (has_bomb[v]) cnt++;
        }
        ans += max(0, cnt - 1); // 关键计算
    }
}
  • 根节点1:子节点2和4的子树含核弹 → cnt=2 → 贡献 1

  • 节点2:子节点5的子树含核弹 → cnt=1 → 贡献 0

  • 总控制器数为 1

邻接表与树构建示例

假设输入边为 1-2, 1-3, 1-4, 2-5,邻接表如下:

1: [2,3,4]
2: [1,5]
3: [1]
4: [1]
5: [2]

通过BFS得到的父子关系:

1的子节点:2,3,4
2的子节点:5
3的子节点:无
4的子节点:无
5的子节点:无

总结

  • 邻接表:存储图结构,每个节点维护相邻节点列表。

  • 树构建:通过BFS确定父子关系,明确树形结构。

  • 后序遍历:自底向上标记子树状态,确保父节点能继承子节点的核弹信息。

  • 控制器计算:每个中转站需要覆盖的子节点数决定控制器数量。

 

 

内容概要:本文研究了计及碳排放的多微网电能交互分布式运行策略,提出了一种基于交替方向乘子法(ADMM)的优化方法,旨在实现多微电网系统在满足能源供需平衡的同时降低碳排放。文中构建了包含分布式电源、储能系统、可控负荷及碳排放约束的多微网协同优化模型,通过ADMM算法将全局优化问分解为各微网子系统独立求解的子问,实现分布式协同调度,在保障各微网自治性的同时兼顾系统整体的经济性与低碳性。研究通过Matlab代码完成了算法仿真,验证了所提策略在提升能源利用效率、减少碳排放、增强系统鲁棒性与可扩展性方面的有效性,为低碳化、去中心化的能源互联网运行提供了理论支持与实践参考。; 适合人群:具备电力系统分析、优化理论及Matlab编程基础的科研人员、电气工程及相关专业的研究生,以及从事智慧能源、分布式能源系统规划与运行的工程技术人员。; 使用场景及目标:①应用于多微电网系统的分布式能量管理与协同优化调度;②支持“双碳”目标下的低碳电网运行策略设计与政策评估;③为ADMM等分布式优化算法在能源系统中的工程化应用提供完整的模型构建、算法实现与仿真验证案例。; 阅读建议:读者应结合Matlab代码深入理解ADMM算法的迭代流程、拉格朗日函数构造与收敛条件设定,重点关注模型中碳排放因子的引入方式、变量分解机制与子问求解过程,建议通过调整微网数量、碳价参数及通信拓扑结构进行多场景仿真,以深化对分布式协同机制与环保经济权衡关系的理解。
下载代码方式:https://pan.quark.cn/s/cc130f55eddd BUCK变换器,亦称为降压型转换器,在开关电源技术中属于一种基础电路拓扑,其核心功能在于实现从高电压到低电压的转换,并且在转换过程中确保输出端电压的稳定性。本文的核心内容集中在对BUCK变换器的运行机制进行剖析、阐释电流连续模式(CCM)与断续模式(DCM)之间的差异,并深入探讨这两种模式在稳态下的相互关系,同时研究BUCK变换器的交流等效电路模型以及电压与电流补偿回路的构建方法。BUCK变换器的原理示意图如图1所示,其显著特征在于输出电压值低于输入电压值,输出电流保持连续状态,而输入电流则呈现出脉动特性。变换器的工作过程可以划分为两个主要阶段:在第一个阶段,即开关管导通期间,电感元件负责储存能量,电流呈现出线性增长的趋势,并且同时向负载提供能量;在第二个阶段,即开关管截止期间,电感通过二极管实现能量的续流,电流则表现出线性递减的态势。依据电感元件的伏秒平衡原理,可以推导出涉及开关管占空比、电感元件电感量、输入电压以及输出电压之间关系的数学公式,这些公式对于深入理解和设计BUCK变换器具有关键性的指导意义。 接下来,文章对CCM和DCM两种模式进行了详细的比较分析。在CCM模式下,电感电流在整个开关周期内均保持连续的状态,而在DCM模式下,电感电流则会出现中断现象。确定BUCK变换器工作模式的关键依据是其电感电流纹波值与输出电流值相等这一边界条件。当电流纹波值等于零,即在整个开关周期内电感电流保持完全连续时,BUCK变换器被归类为CCM模式;相对地,若电流纹波值大于零,则表明变换器处于DCM模式;介于两者之间的情况则界定为CCM与DCM的过渡状态。 在DCM模式下,对BUCK...
源码链接: https://pan.quark.cn/s/ae09e867d64c S参数指的是散射参数,其英文全称为“Scattering-Parameter”。该参数用于表征电路网络中信号传输与反射的特性,是微波领域中衡量电路网络性能的核心指标。以二端口网络为例,比如单根传输线,其包含四个S参数,分别为S11、S12、S21和S22。其中,S11代表端口1的反射系数,S12代表端口1至端口2的反向传输系数,S21代表端口2至端口1的正向传输系数,而S22则表示端口2的反射系数。在高速电路设计领域,S参数是评估电路网络性能的关键依据。对于互易性网络,存在S12=S21的关系;对于对称性网络,满足S11=S22的条件;而对于无耗性网络,则有S11*S11+S21*S21=1,即网络不产生能量损耗,从端口1输入的能量要么被反射回端口1,要么被传输至端口2。在实际应用场景中,S参数能够用于评估电路网络的性能表现,例如,S11体现回波损耗,即有多少能量被反射回源端(Port1),该值越小越好,通常推荐S11<0.1,即-20dB。S21则反映插入损耗,即有多少能量被传输到目的端(Port2),该值越大越优,理想值为1,即0dB,传输效率越高,一般建议S21>0.7,即-3dB。此外,S参数还可用于判断电路网络的互易性与对称性。在高速电路设计过程中,这些参数具有显著意义,因为它们对电路网络的性能和稳定性具有直接影响。S参数是评估电路网络性能的核心指标,能够衡量电路网络的信号传输和反射能力,对于高速电路设计而言至关重要。关于Z参数和Smith圆图,Z参数属于阻抗参数,而Smith圆图是反射系数(以符号Γ表示)的极坐标图形。Smith圆图可用于评估电路网络的阻抗匹配状况...
内容概要:本文围绕基于序贯蒙特卡洛模拟法的配电网可靠性评估展开研究,系统阐述了该方法在电力系统中的应用原理与实现路径。通过Matlab代码实现了系统状态抽样、状态分析、可靠性指标计算等关键环节,并结合IEEE标准测试系统进行仿真验证,有效评估配电网在不同运行工况下的可靠性水平。研究不仅提供了完整的算法实现框架,还拓展至阶梯式碳交易、供需响应、N-k安全约束等多种复杂场景,体现了其在现代综合能源系统优化中的广泛适用性。配套资源丰富,涵盖多个电力系统前沿研究方向的技术实现与论文复现案例。; 适合人群:具备电力系统基础知识和Matlab编程能力的科研人员与工程技术人员,特别适用于从事配电网可靠性分析、综合能源系统优化、电力系统仿真等领域的高校研究生、科研机构研究人员及电力行业工程师。; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在配电网可靠性评估中的建模与仿真方法;②学习利用Matlab进行电力系统随机模拟与数据分析;③为电网规划、运行风险评估及故障恢复策略制定提供量化依据;④拓展对智能优化算法、机器学习及多能协同调度在电力系统中集成应用的理解。; 阅读建议:此资源不仅提供可运行的Matlab代码,还融合了大量科研实践案例,建议读者结合文中仿真模型与实际算例进行动手复现,深入理解算法细节与工程背景,同时关注相关领域如微电网优化、故障诊断、路径规划等交叉技术的发展,以提升综合科研与工程应用能力。
源码直接下载地址: https://pan.quark.cn/s/9af8b9f95652 ### Multisim模型的导入和使用 ### 一、引言 随着电子设计自动化(EDA)工具的进步,Multisim已经成为电子工程师进行电路仿真、分析和设计的关键工具之一。借助Multisim,工程师们能够便捷地构建电路模型,并对电路进行仿真验证。本文将系统阐述如何在Multisim中导入并运用芯片仿真模型,这对于提升电子产品的研发效能具有显著价值。 ### 二、Multisim中构建新元器件 构建新元器件是Multisim中的核心功能,特别是对于那些需要特定模型或无法从Multisim库中直接获取的元器件来说更为关键。以下为构建新元器件的具体流程: ##### 步骤1:录入元器件信息 在Multisim中启动“Component Wizard”,即元器件向导,开始创建新的元器件。首先需要录入元器件的基本资料,包括型号、主要功能、类型等。这些资料将有助于用户更高效地管理和检索元器件。 ##### 步骤2:录入封装信息 接下来需要设定元器件的封装信息。在这一环节中,用户需要依据实际芯片的封装规格来选择适宜的引脚数量。同时,还需明确是构建单一部件元器件还是复合部件元器件。如果是复合部件元器件,则必须确保引脚数量与符号中使用的引脚数量保持一致。 ##### 步骤3:录入符号信息 在此步骤中,用户可以编辑元器件在仿真过程中的显示符号。编辑符号可以通过三种途径进行:直接编辑、从数据库中复制现有符号或复制当前符号以备将来使用。编辑符号时应注重其在电路图中的可辨识度和清晰度。 ##### 步骤4:设定管脚参数 在该步骤中,用户需要参照数据手册上的管脚顺序为每个管脚命名,并选择恰当的类型。...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值