转自:https://www.cnblogs.com/Ash-ly/p/5783877.html

一:最小支配集

考虑最小支配集,每个点有两种状态,即属于支配集合或者不属于支配集合,其中不属于支配集合时此点还需要被覆盖,被覆盖也有两种状态,即被子节点覆盖或者被父节点覆盖.总结起来就是三种状态,现对这三种状态定义如下:

1):dp[i][0],表示点 i 属于支配集合,并且以点 i 为根的子树都被覆盖了的情况下支配集中所包含最少点的个数.

2):dp[i][1],表示点 i 不属于支配集合,且以 i 为根的子树都被覆盖,且 i 被其中不少于一个子节点覆盖的情况下支配集所包含最少点的个数.

3):dp[i][2],表示点 i 不属于支配集合,且以 i 为根的子树都被覆盖,且 i 没被子节点覆盖的情况下支配集中所包含最少点的个数.即 i 将被父节点覆盖.

对于第一种状态,dp[i][0]含义为点 i 属于支配集合,那么依次取每个儿子节点三种状态中的最小值,再把取得的最小值全部加起来再加 1,就是dp[i][0]的值了.即只要每个以 i 的儿子为根的子树都被覆盖,再加上当前点 i,所需要的最少的点的个数,DP转移方程如下:

dp[i][0] = 1 + ∑(u 取 i 的子节点)min(dp[u][0], dp[u][1], dp[u][2])

对于第三种状态,dp[i][2]含义为点 i 不属于支配集合,且 i 被其父节点覆盖.那么说明点 i 和点 i 的儿子节点都不属于支配集合,所以点 i 的第三种状态之和其儿子节点的第二种状态有关,方程为:

dp[i][2] = ∑(u 取 i 的子节点)dp[u][1]

对于第二种状态,略有些复杂.首先如果点 i 没有子节点那么 dp[i][1]应该初始化为 INF;否则为了保证它的每个以 i 的儿子为根的子树被覆盖,那么要取每个儿子节点的前两种状态的最小值之和,因为此时点 i 不属于支配集,不能支配其子节点,所以子节点必须已经被支配,与子节点的第三种状态无关.如果当前所选状态中每个儿子都没被选择进入支配集,即在每个儿子的前两种状态中,第一种状态都不是所需点最小的,那么为了满足第二种状态的定义(因为点 i 的第二种状态必须被其子节点覆盖,即其子节点必须有一个属于支配集,如果此时没有,就必须强制使一个子节点的状态为状态一),需要重新选择点 i 的一个儿子节点为第一种状态,这时取花费最少的一个点,即取min(dp[u][0] - dp[u][1])的儿子节点 u,强制取其第一种状态,其他的儿子节点取第二种状态,DP转移方程为:

if(i 没有子节点)   dp[i][1] = INF

else                   dp[i][1] = ∑(u 取 i 的子节点)min(dp[u][0], dp[u][1]) + inc

其中对于 inc 有:

if(上面式子中的 ∑(u 取 i 的子节点)min(dp[u][0], dp[u][1]) 中包含某个 dp[u][0], 即存在一个所选的最小值为状态一的儿子节点) inc = 0

else    inc = min(dp[u][0] - dp[u][1])  (其中 u 取点 i 的儿子节点)

代码:

void DP(int u, int p) {// p 为 u 的父节点dp[u][2] = 0;dp[u][0] = 1;bool s = false;int sum = 0, inc = INF;for(int k = head[u]; k != -1; k = edge[k].next) {int to = edge[k].to;if(to == p) continue;DP(to, u);dp[u][0] += min(dp[to][0], min(dp[to][1], dp[to][2]));if(dp[to][0] <= dp[to][1]) {sum += dp[to][0];s = true;}else {sum += dp[to][1];inc = min(inc, dp[to][0] - dp[to][1]);}if(dp[to][1] != INF && dp[u][2] != INF) dp[u][2] += dp[to][1];else dp[u][2] = INF;}if(inc == INF && !s) dp[u][1] = INF;else {dp[u][1] = sum;if(!s) dp[u][1] += inc;}
}

二:最小点覆盖

对于最小点覆盖,每个点只有两种状态,即属于点覆盖或者不属于点覆盖:

1):dp[i][0]表示点 i 属于点覆盖,并且以点 i 为根的子树中所连接的边都被覆盖的情况下点覆盖集中所包含最少点的个数.

2):dp[i][1]表示点 i 不属于点覆盖,且以点 i 为根的子树中所连接的边都被覆盖的情况下点覆盖集中所包含最少点的个数.

对于第一种状态dp[i][0],等于每个儿子节点的两种状态的最小值之和加 1,DP转移方程如下:

dp[i][0] = 1 + ∑(u 取 i 的子节点)min(dp[u][0], dp[u][1])

对于第二种状态dp[i][1],要求所有与 i 连接的边都被覆盖,但是点 i 不属于点覆盖,那么点 i 的所有子节点就必须属于点覆盖,即对于点 i 的第二种状态与所有子节点的第一种状态有关,在数值上等于所有子节点第一种状态的和.DP转移方程如下:

dp[i][1] = ∑(u 取 i 的子节点)dp[u][0]

代码:

void DP(int u, int p) {// p 为 u 的父节点dp[u][0] = 1;dp[u][1] = 0;for(int k = head[u]; k != -1; k = edge[k].next) {int to = edge[k].to;if(to == p) continue;DP(to, u);dp[u][0] += min(dp[to][0], dp[to][1]);dp[u][1] += dp[to][0];}
}

三:最大独立集

对于最大独立集,每个点也只有两种状态,即属于点 i 属于独立集或者不属于独立集两种情况:

1):dp[i][0]表示点 i 属于独立集的情况下,最大独立集中点的个数.

2):dp[i][1]表示点 i 不属于独立集的情况下.最大独立集中点的个数.

对于第一种状态dp[i][0],由于 i 点属于独立集,所以它的子节点都不能属于独立集,所以对于点 i 的第一种状态,只和它的子节点的第二种状态有关.等于其所有子节点的第二种状态的值加 1,DP转移方程如下:

dp[i][0] = 1 + ∑(u 取 i 的子节点) dp[u][1]

对于第二种状态dp[i][1],由于点 i 不属于独立集,所以子节点可以属于独立解,也可以不属于独立集,所取得子节点状态应该为数值较大的那个状态,DP转移方程:

dp[i][1] = ∑(u 取 i 的子节点)max(dp[u][0], dp[u][1])

代码:

void DP(int u, int p) {// p 为 u 的父节点dp[u][0] = 1;dp[u][1] = 0;for(int k = head[u]; k != -1; k = edge[k].next) {int to = edge[k].to;if(to == p) continue;DP(to, u);dp[u][0] += dp[to][1];dp[u][1] += max(dp[to][0], dp[to][1]);}
}

参考文献《图论及应用》,以及部分网上的资料.

树形DP求树的最小支配集,最小点覆盖,最大独立集相关推荐

  1. 贪心法求树的最小支配集,最小点覆盖,最大独立集

    原文地址(转自 Ashly的博客) 定义: 最小支配集:对于图G = (V, E) 来说,最小支配集指的是从 V 中取尽量少的点组成一个集合, 使得 V 中剩余的点都与取出来的点有边相连.也就是说,设 ...

  2. 旅游(树形dp求树的最大独立集)

    链接:https://ac.nowcoder.com/acm/problem/15748 来源:牛客网 题目描述 Cwbc和XHRlyb生活在s市,这天他们打算一起出去旅游. 旅行地图上有n个城市,它 ...

  3. 树上子链(树形dp求树的直径)

    树上子链 题意: 给定一棵树 T ,树 T 上每个点都有一个权值. 定义一颗树的子链的大小为:这个子链上所有结点的权值和 . 请在树 T 中找出一条最大的子链并输出. 题解: 求树的直径,题目中存在负 ...

  4. 1579: 【例 5】皇宫看守(最小支配集——贪心求解/树形DP)

    [题目描述] 太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫. 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状,某些宫殿间可以互相望见.大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全 ...

  5. [UVA-1218] Perfect Service(树的最小支配集)

    题目链接:https://vjudge.net/problem/UVA-1218 题目大意:给你一棵无向树,让你求树的最小支配集,但是有一个要求是除最小支配集外剩下的任何一个结点不能同时连接支配集中的 ...

  6. 最小支配集,最小点覆盖,最大独立集(贪心/DP)

    最小支配集(minimal dominating set):对于图G=(V,E)来说,设V'是图G的一个支配集,则对于图中的任意一个顶点u,要么属于集合V',要么与V'中的顶点相连. 在V'中除去任何 ...

  7. 树的最小支配集、最小点覆盖、最大独立集【模板】

    最小支配集:指从所有顶点中取尽量少的点组成一个集合,使得剩下的所有点都与取出来的点有边相连.顶点个数最小的支配集被称为最小支配集.这里用贪心法来求. 1.以1号点深度优先搜索整棵树,求出每个点在DFS ...

  8. 牛客假日团队赛8:H.Cell Phone Network(最小支配集)

    链接:https://ac.nowcoder.com/acm/contest/1069/A 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言6553 ...

  9. *【POJ - 3659】Cell Phone Network (树形dp,最小支配集)

    题干: Farmer John has decided to give each of his cows a cell phone in hopes to encourage their social ...

最新文章

  1. CRM中Plugin开发如何将功能放入多个模块
  2. 庄闲分析软件安卓版_关于公布湖南省2020年第七批软件产品评估结果的通知
  3. python用户交互、基本数据类型、运算符
  4. (转)海岸线提取完成, 海浪排岸效果
  5. java多态 覆盖_Java ------ 继承、方法覆盖、多态
  6. 华为客户端优化建议(应用保活相关)
  7. vSphere虚拟化使用第三方备份方案常见CBT故障实战处理
  8. 吊打 IE、Firefox,谷歌 Chrome 十年封神记
  9. 【前端 · 面试 】HTTP 总结(六)—— HTTP 版本区别
  10. eclipse Android开发——布局查看
  11. 函数不可以直接调用其他函数内部定义的变量_JavaScript(4) 函数
  12. 数字逻辑实验-交通灯控制设计
  13. Cisco 防火墙 ASA DHCP 配置
  14. 如何将三维模型移动到真实位置
  15. 输入阻抗、输出阻抗与阻抗匹配
  16. 子母钟时钟系统工业应用
  17. 华三路由器RIP协议详细配置
  18. iOS 日本日历、佛教日历取date的问题及公历转换,时间戳获取不准确
  19. Qt无边框窗体实现方案
  20. 手机计算机怎么缩小桌面图标,桌面图标怎么变小-iPhone图标突然变大?不要方,来看看这几招...

热门文章

  1. man mysql_几个容易被忽略的mysql知识
  2. docker 不包含依赖 打包_Docker容器技术(概念篇)
  3. CORS 跨域-同源策略
  4. Pod详解-生命周期-创建和终止
  5. Java并发编程的基础-Thread.interrupted
  6. maven项目概念模型图
  7. 微服务网关-Gateway-LoadBalancerClient实现负载均衡讲解
  8. mybatisdb.sql
  9. 使用Java读取 “Python写入redis” 的数据踩坑记录
  10. 第四单元用计算机写作,计算机复习题