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")
相关推荐
minji...1 小时前
Linux 库制作与原理(三)深入动静态链接原理
linux·运维·服务器·c++
lihihi2 小时前
P1209 [USACO1.3] 修理牛棚 Barn Repair
算法
weixin_387534222 小时前
Ownership - Rust Hardcore Head to Toe
开发语言·后端·算法·rust
庞轩px2 小时前
MinorGC的完整流程与复制算法深度解析
java·jvm·算法·性能优化
Queenie_Charlie2 小时前
Manacher算法
c++·算法·manacher
闻缺陷则喜何志丹2 小时前
【树的直径 离散化】 P7807 魔力滋生|普及+
c++·算法·洛谷·离散化·树的直径
AI_Ming2 小时前
Seq2Seq-大模型知识点(程序员转行AI大模型学习)
算法·ai编程
若水不如远方3 小时前
分布式一致性(六):拥抱可用性 —— 最终一致性与 Gossip 协议
分布式·后端·算法
计算机安禾3 小时前
【C语言程序设计】第35篇:文件的打开、关闭与读写操作
c语言·开发语言·c++·vscode·算法·visual studio code·visual studio