题解 | 在树上游玩

在树上游玩

https://www.nowcoder.com/practice/8c0d60834a924ce98e7425fed9c62ab8

#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; // 如果节点v已经被访问过,直接返回
    vis[v] = true; // 标记节点v为已访问
    for(int i=0; i<G[v].size(); i++){ // 遍历节点v的所有邻接点
        if(masked[G[v][i]] && vis[G[v][i]] == false){ // 若邻接点是标记节点且未被访问
            DFS(G[v][i], cnt); // 继续深度优先搜索
        }else if(vis[G[v][i]] == false){ // 若邻接点未被访问且不是标记节点
            cnt++; // neighbor数量加1
        }
    }
}

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; // ans存储染色方案数量,cost存储最小染色代价
    for(int i=1; i<=n; i++){ // 遍历所有节点
        if(masked[i] && vis[i] == false){ // 若节点是标记节点且未被访问
            int cnt = 0; // 初始化neighbor数量
            DFS(i, cnt); // 统计neighbor数量
            cost++; // 最小代价为标记节点连通块数量
            ans = (ans * cnt) % MOD; // 方案数为当前方案数乘上每个连通块的邻居节点数量
        }
    }
    cout << cost << ' ' << ans; // 输出结果
    return 0;
}

全部评论

相关推荐

04-29 22:35
门头沟学院 Java
牛友说改了名字能收到offer:旧图新发查看图片
点赞 评论 收藏
分享
刘湘_passion:出国旅游?那就小心你的腰子咯
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务