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")
相关推荐
大熊背13 分钟前
如何利用Lv值实现三级降帧
算法·自动曝光·lv·isppipeline
大尚来也30 分钟前
驾驭并发:.NET多线程编程的挑战与破局之道
java·前端·算法
向阳而生,一路生花34 分钟前
深入浅出 JDK7 HashMap 源码分析
算法·哈希算法
君义_noip1 小时前
信息学奥赛一本通 4150:【GESP2509七级】⾦币收集 | 洛谷 P14078 [GESP202509 七级] 金币收集
c++·算法·gesp·信息学奥赛·csp-s
Ricky_Theseus1 小时前
静态链接与动态链接
c++
摸个小yu1 小时前
【力扣LeetCode热题h100】链表、二叉树
算法·leetcode·链表
汀、人工智能1 小时前
[特殊字符] 第93课:太平洋大西洋水流问题
数据结构·算法·数据库架构·图论·bfs·太平洋大西洋水流问题
ZPC82101 小时前
rviz2 仿真控制器与真实机器人切换
人工智能·算法·机器人
澈2072 小时前
双指针,数组去重
c++·算法
小辉同志2 小时前
207. 课程表
c++·算法·力扣·图论