首页 > 其他分享 >换根dp

换根dp

时间:2023-03-15 12:44:53浏览次数:26  
标签:int dfs 换根 根为 节点 Bob 猜测 dp

问题

Alice 有一棵 n 个节点的树,节点编号为 0 到 n - 1 。树用一个长度为 n - 1 的二维整数数组 edges 表示,其中 edges[i] = [ai, bi] ,表示树中节点 ai 和 bi 之间有一条边。

Alice 想要 Bob 找到这棵树的根。她允许 Bob 对这棵树进行若干次 猜测 。每一次猜测,Bob 做如下事情:

  • 选择两个 不相等 的整数 u 和 v ,且树中必须存在边 [u, v] 。
  • Bob 猜测树中 u 是 v 的 父节点 。

Bob 的猜测用二维整数数组 guesses 表示,其中 guesses[j] = [uj, vj] 表示 Bob 猜 uj 是 vj 的父节点。

Alice 非常懒,她不想逐个回答 Bob 的猜测,只告诉 Bob 这些猜测里面 至少 有 k 个猜测的结果为 true 。

给你二维整数数组 edges ,Bob 的所有猜测和整数 k ,请你返回可能成为树根的 节点数目 。如果没有这样的树,则返回 0

示例

输入:edges = [[0,1],[1,2],[1,3],[4,2]], guesses = [[1,3],[0,1],[1,0],[2,4]], k = 3
输出:3
解释:
根为节点 0 ,正确的猜测为 [1,3], [0,1], [2,4]
根为节点 1 ,正确的猜测为 [1,3], [1,0], [2,4]
根为节点 2 ,正确的猜测为 [1,3], [1,0], [2,4]
根为节点 3 ,正确的猜测为 [1,0], [2,4]
根为节点 4 ,正确的猜测为 [1,3], [1,0]
节点 0 ,1 或 2 为根时,可以得到 3 个正确的猜测。

输入:edges = [[0,1],[1,2],[2,3],[3,4]], guesses = [[1,0],[3,4],[2,1],[3,2]], k = 1
输出:5
解释:
根为节点 0 ,正确的猜测为 [3,4]
根为节点 1 ,正确的猜测为 [1,0], [3,4]
根为节点 2 ,正确的猜测为 [1,0], [2,1], [3,4]
根为节点 3 ,正确的猜测为 [1,0], [2,1], [3,2], [3,4]
根为节点 4 ,正确的猜测为 [1,0], [2,1], [3,2]
任何节点为根,都至少有 1 个正确的猜测。

分析

这道题考察的是【换根DP】

先考虑暴力做法,就是枚举每个节点作为根节点,然后进行dfs,统计答案,而使用换根dp则是通过一下几个步骤来进行求解的

  • 随便选一个点作为根节点,通过一次dfs收集我们需要的信息
  • 考虑如果更换树根,答案能否通过上一次收集的信息转化而来,不再枚举剩余的节点作为根节点再dfs整颗树
  • 再进行一次dfs,dfs的过程就是换根的过程,通过已经收集的信息推出答案
  • 一共只需要两次dfs

对于本题,我们发现更换根节点只影响新的树根和他原来的父节点的父子关系,比如:

在示例一中,将根由0换成1,那么[0, 1]就由正确的变为错误的,而[1, 0]就由错误的变成了正确的了,即cnt1 = cnt0 - [0, 1] in guesses + [1, 0] in guesses,因此:

  • 把以 0 为根节点进行一次dfs,计算出猜对的次数cnt0
  • 再跑一遍dfs,进行换根,根据已知的信息推出不同的根下的猜对的次数

Code

class Solution {
    static const int N = 100010, M = 2 * N;
    int h[N], e[M], ne[M], idx = 0;
    int cnt0 = 0, res = 0, k;
    set<long > s; 
    void add(int a, int b) {
        e[idx] = b, ne[idx] = h[a], h[a] = idx++;
    }
    void dfs1(int u, int p) {
        for (int i = h[u]; i != -1; i = ne[i]) {
            int j = e[i];
            if (j != p) {
                if (s.count(((long)u << 32) | j)) cnt0++;
                dfs1(j, u);
            }
        }
    }
    void dfs2(int u, int p, int cnt) {
        // cnt是以u为根的猜对的数量
        if (cnt >= k) res++;
        // 换根
        for (int i = h[u]; i != -1; i = ne[i]) {
            int j = e[i];
            if (j != p) {
                dfs2(j, u, cnt - s.count(((long)u << 32) | j) + s.count(((long)j << 32) | u));
            }
        }
    }
public:
    int rootCount(vector<vector<int>>& edges, vector<vector<int>>& guesses, int _k) {
        // 建图
        memset(h, -1, sizeof h);
        for (auto &edge : edges) {
            add(edge[0], edge[1]);
            add(edge[1], edge[0]);
        }
        // hash guess数组实现O(1)的询问
        for (auto &guesse : guesses) s.insert(((long)guesse[0] << 32 ) | guesse[1]);
        dfs1(0, -1);
        k = _k;
        dfs2(0, -1, cnt0);
        return res;
    }
};

标签:int,dfs,换根,根为,节点,Bob,猜测,dp
From: https://www.cnblogs.com/chenjq12/p/17218068.html

相关文章

  • 高维前缀和(SOSDP)
    高维前缀和(SOSdp)AXorBProblemagain二维前缀和for(inti=1;i<=n;i++)for(intj=1;j<=n;j++)s[i][j]=s[i-1][j]+s[i][j-1]-......
  • 2023.3.14 状压 dp 模拟赛题解
    好强啊。不说是谁了,都好强啊呜呜呜。   首先T1的一个优化luoguP1842奶牛玩杂技,需要一个贪心排序来优化序列顺序。关于贪心排序:像这样有两种及以上性质的序列,......
  • wordpress做外贸站
    WooCommerce价格,是否有域名限制WooCommerce是一个免费的WordPress插件,可以让您在WordPress网站上创建和运行在线商店。但是,要使用WooCommerce,您还需要支付一些其他费用,......
  • 安卓 存储---SharedPreferences
    导包importandroid.content.SharedPreferences;importandroid.content.SharedPreferences.Editor;存储数据//创建应用级首选项SharedPreferencessharedPreferences=ge......
  • XTB股价创下历史新高,Finalto推出ODP流动性解决方案
    我们都知道,上周成为外汇热门的新闻是MetaQuotes和苹果达成共识,MT4/5交易应用程序重新上架AppleAppStore,对此天眼君也回顾了当时苹果下架MT4/5的原因,此次上架也获得了广大......
  • 【CF1572C Paint】(区间dp)
    原题链接题意给定长度为\(n\)的颜色序列\(a_i\),每次你可以选择任意长度的连续且颜色相同的一段位置,将其全部变成任意同一种颜色,问你最少总共需要多少次操作才能使得整......
  • 【LOJ 3378】点格棋(DP)(推论)
    点格棋题目链接:LOJ3378题目大意有一个(n+1)*(m+1)的格点组成的网格,然后两个人轮流操作,选两个相邻(距离为1)且没有连边的点对连一个竖直或者水平的线段。然后如果一个......
  • ovs-dpdk:revalidator源码解析
    revalidator是做什么的?需要知道哪些东西?有关于revalidator需要弄明白的是以下三个问题:通过ovs-vsctllistopen_vs可以看到other_config里面有两个变量线程数配置:n-han......
  • 4.docker错误Error response from daemon: driver failed programming external conne
    1.docker端口映射或启动容器时报错Errorresponsefromdaemon:driverfailedprogrammingexternalconnectivityonendpointquirky_allenErrorresponsefromdaemon......
  • Ubuntu系统将对HiDPI提供更好的支持
    Canonical的MichaelHall和System76社区经理RyanSipes发布联合声明,宣布两家公司将开展合作在Ubuntu Linux系统上改善对HiDPI的支持。事实上,上周System76的一组工程团......