ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

cf1695 D2. Tree Queries (Hard Version)

2022-06-21 01:33:21  阅读:158  来源: 互联网

标签:子树 int 询问 Hard Tree mid dfs 子树中 cf1695


题意:

给定一棵边权为1的树,树中有一个特殊节点但不告诉你是哪个。你可以询问一个节点集 \(S\),然后知道特殊点到 \(S\) 中每个点的距离。输出能确定特殊点的 \(|S|\) 的最小值

\(n\le 2e5\)

思路:

题目转化为:对任意点 \(u\),怎样区分特殊点与 \(u\)?

再转化为:要能区分任意两点。即对任意两点 \(u\neq v\),存在点 \(x\in S\),\(dis_{x,u}\neq dis_{x,v}\)

若 \(u\) 到 \(v\) 的距离为奇数,那只要整棵树中至少有一个询问点就能区分 \(u,v\) 了

若 \(u\) 到 \(v\) 的距离为偶数,设 \(u\) 到 \(v\) 的链形如 \(u-\dots -x-mid-y-\dots v\),其中 \(mid\) 是中点(即 \(dis_{mid,u}=dis_{mid,v}\))

为方便叙述,暂时把 \(mid\) 看成根——那么 \(x\)子树或 \(y\)子树中至少要有一个询问点

最终结论:对任一节点 \(u\),设 \(u\) 的邻点们为 \(v_i\),则最多只有一棵 \(v_i\)子树可以没有询问点

怎么实现呢?设当 \(u\) 不为根时,\(ans[u]\) 表示 \(u\)子树之外已经有询问点的情况下,\(u\)子树中至少要选几个点。dfs 时统计 \(u\) 有几个 “子树中没有询问点的儿子”,最多允许一个儿子的子树中没有询问点

怎么保证 “\(u\)子树之外已经有询问点”?

若整棵树的根节点的度大于等于3,这肯定满足;

而若根节点的度为2,有可能 \(u\)子树之外没有询问点。所以我们可以选一个度数大于等于3的点开始 dfs 以避免这种情况;

如果找不到度数大于等于3的点说明整棵树是一条链,答案是1;另外还要特判整棵树只有一个点的情况

int n, d[N]; vector<int> G[N];

int dfs(int u, int fa) {
    int ans = 0, cnt = 0; //子树中没有点的儿子的数量
    for(int v : G[u]) if(v != fa) {
        int t = dfs(v, u);
        if(t) ans += t; else cnt++;
    }
    return ans + max(0, cnt - 1);
}

int sol() {
    int n; cin >> n;
    for(int i = 1; i <= n; i++) G[i].clear(), d[i] = 0;
    for(int i = 1; i < n; i++) {
        int x, y; cin >> x >> y;
        G[x].pb(y), G[y].pb(x);
        d[x]++, d[y]++;
    }

    if(n == 1) return 0; //只有一个点

    for(int i = 1; i <= n; i++)
        if(d[i] >= 3) return dfs(i, 0);
    
    return 1; //链
}

标签:子树,int,询问,Hard,Tree,mid,dfs,子树中,cf1695
来源: https://www.cnblogs.com/wushansinger/p/16395347.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有