HJ138 在树上游玩

  • 题目
  • 题解(12)
  • 讨论(5)
  • 排行

较难 通过率:38.07% 时间限制:1秒 空间限制:1024M

知识点动态规划

校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。

描述

对于给定的由 nn 个节点组成的无根树,每一条边都可以被染上颜色,初始时,全部边均为白色。

现在,选中树上 kk 个不同的点,并将它们标记,随后,定义,如果一条树边 (u,v)(u,v) 满足节点 uu 和 vv 同时被标记,那么这条树边自动被染为红色,不需要花费任何代价。

现在,你可以额外选择一些树边,将它们染成红色,每染一条边需要花费 11 点代价。

请你计算最小的染色代价,使得任意一个被标记的点都可以通过被染成红色的边到达至少一个未被标记的点。并输出不同的染色方案数量。

输入描述:

第一行输入两个整数 n,k(2≦n≦105; 1≦k<n)n,k(2≦n≦105; 1≦k<n) 代表树的节点数、被标记的点数。

第二行输入 kk 个不同的整数 a1,a2,...,ak(1≦ai≦n)a1​,a2​,...,ak​(1≦ai​≦n) 代表被标记的点的编号。

此后 n−1n−1 行,第 ii 行输入两个整数 ui,vi(1≦ui,vi≦n,ui≠vi)ui​,vi​(1≦ui​,vi​≦n,ui​​=vi​) 代表第 ii 条树边连接 uiui​ 和 vivi​。

输出描述:

在一行上输出两个整数,代表最小的染色代价、满足条件的染色方案数量。由于染色方案数量可能很大,请输出对 109+7109+7 取模后的结果。

示例1

输入:

复制代码
11 6
8 2 4 7 9 6
8 10
8 9
1 8
1 11
1 3
11 2
5 6
2 5
4 2
7 6

复制输出:

复制代码
3 4

复制说明:

复制代码
在这个样例中,树的形态如下图所示。

TOP

ACM 模式

是否格式化代码?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

时间限制:C/C++ 1秒,其他语言

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;
typedef long long LL;
const int MOD = 1e9 + 7;
const int maxn = 200005;
bool vis[maxn] ={false};
bool masked[maxn] = {false};
vector<int> G[maxn]; // 邻接表

// 统计v能到达的neighbor数量
void DFS(int v, int &cnt){
    if(vis[v]) return;
    vis[v] = true;
    for(int i=0; i<G[v].size(); i++){
        if(masked[G[v][i]] && vis[G[v][i]] == false){ // 若是标记节点继续深入搜索
            DFS(G[v][i], cnt);
        }else if(vis[G[v][i]] == false){ // 若是没有访问的邻居节点
            cnt++;
        }
    }
}

int main() {
    int n, k, u, v;
    cin >> n >> k;
    for(int i=0; i<k; i++){
        cin >> v;
        masked[v] = true;
    }
    for(int i=0; i<n-1; i++){
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    LL ans = 1, cost = 0;
    for(int i=1; i<=n; i++){
        if(masked[i] && vis[i] == false){
            int cnt = 0;
            DFS(i, cnt);
            cost++; // 最小代价为标记节点连通块数量
            ans = (ans * cnt) % MOD; // 方案数为当前方案数乘上每个连通块的邻居节点数量
        }
    }
    cout << cost << ' ' << ans;
    return 0;
}
// 64 位输出请用 printf("%lld")
相关推荐
吃好睡好便好14 小时前
在Matlab中绘制横直方图
开发语言·学习·算法·matlab
仰泳之鹅15 小时前
【C语言】自定义数据类型2——联合体与枚举
c语言·开发语言·算法
于小猿Sup16 小时前
VMware在Ubuntu22.04驱动Livox Mid360s
linux·c++·嵌入式硬件·自动驾驶
x_yeyue17 小时前
三角形数
笔记·算法·数论·组合数学
念何架构之路18 小时前
Go语言加密算法
数据结构·算法·哈希算法
AI科技星18 小时前
《数学公理体系·第三部·数术几何》(2026 年版)
c语言·开发语言·线性代数·算法·矩阵·量子计算·agi
小小编程路18 小时前
C++ 多线程与并发
java·jvm·c++
失去的青春---夕阳下的奔跑18 小时前
560. 和为 K 的子数组
数据结构·算法·leetcode
黎阳之光19 小时前
黎阳之光:以视频孪生重构智慧医院信息化,打造高标项目核心竞争力
大数据·人工智能·物联网·算法·数字孪生
丷丩19 小时前
三级缓存下MVT地图瓦片服务性能优化策略
算法·缓存·性能优化·gis·geoai-up