树的最小支配集 最小点覆盖 与 最大独立集 (图论)

做 战略游戏 这道题的时候看到了这个东西,于是就来这里写了一下.

首先看一下三者的定义:

  定义1  对于图G=(V,E)来说,最小支配集指的是从V中取尽量少的点组成一个集合,使得对于V中剩余的点都与取出来的点有边相连。也就是说,设V‘是图G的一个支配集,则对于图中的任意一个顶点u,要么属于集合V’,要么与V‘中的顶点相邻。在V’中出去任何元素后V‘不再是支配集,则支配集是极小支配集。称G的所有支配集中顶点个数最少的支配集为最小支配集,最小支配集中顶点的个数称为支配数。

  定义2  对于图G=(V,E)来说,最小点覆盖指的是从V中取尽量少的点组成一个集合,使得E中所有的边都与取出来的点相连。也就是说,设V‘是图G的一个顶点覆盖,则对于图中的任意一条边(u,v),要么u属于集合V’,要么v属于集合V‘。在V‘中除去任何元素后V’不在是顶点覆盖,则V‘是极小顶点覆盖。称G的所有顶点覆盖中顶点个数最少的覆盖为最小点覆盖。

  定义3  对于图G=(V,E)来说,最大独立集指的是从V中取尽量多的点组成一个集合,使得这些点之间没有边相连。也就是说,设V’是图G的一个独立集,则对于图中任意一条边(u,v),u和v不能同时属于集合V‘,甚至可以u和v都不属于集合V‘。在V’中添加任何不属于V‘元素后V’不再是独立集,则V‘是极大独立集。称G的所有顶点独立集中顶点个数最多的独立集为最大独立集。  

  对于任意图G来说,这三个问题不存在多项式时间的解法。不过对于树来说,却很容易。目前有两种解法,一种基于贪心思想,另一种基于树形动态规划思想。 

  一:贪心法

  基本算法:

  以最小支配集为例,对于树上的最小支配集问题,贪心策略是首先选择一点为根,按照深度优先遍历得到遍历序列,按照所得序列的反向序列的顺序进行贪心,对于一个既不属于支配集也不与支配集中的点相连的点来说,如果他的父节点不属于支配集,将其父节点加入支配集。

  这里注意到贪心的策略中贪心的顺序非常重要,按照深度优先遍历得到遍历序列的反向进行贪心,可以保证对于每个点来说,当期子树都被处理过后才轮到该节点的处理,保证了贪心的正确性。

  伪代码:

  ①以1号点深度优先搜索整棵树,求出每个点在深度优先遍历序列中的编号和每个点的父节点编号。

  ②按照深度优先序列的反向序列检查,如果当前点既不属于支配集也不与支配集中的点相连,且他的父节点不属于支配集,将其父节点加入支配集,支配集中点的个数加1.标记当前节点、当前节点的父节点和当前节点的父节点的父节点,因为这些节点要么属于支配集,要么与支配集中的点相连。

  最小点覆盖于最大独立集与上面的做法相似。对于最小点覆盖来说,贪心的策略是,如果当前点和当前点的父节点都不属于顶点覆盖集合,则将父节点加入到顶点覆盖集合,并标记当前节点和其父节点都被覆盖。对于最大独立集来说,贪心策略是如果当前点没有被覆盖,则将当前节点加入到独立集,并标记当前节点和其父节点都被覆盖。

  需要注意的是由于默认程序中根节点和其他节点的区别在于根节点的父节点是其自己,所以三种问题对根节点的处理不同。对于最小支配集和最大独立集,需要检查根节点是否满足贪心条件,但是对于最小点覆盖不可以检查根节点。

  具体实现:

  采用链式前向星存储整棵树。对于DFS(),newpos[i]表示深度优先遍历序列的第i个点是哪个点,now表示当前深度优先遍历序列已经有多少个点了。select[]用于深度优先遍历序列的判重,p[i]表示点i的父节点的编号。对于greedy(),s[i]如果为true,表示第i个点被覆盖。set[i]表示点i属于要求的点集。

  首先是深度优先遍历,得到遍历序列。代码如下:

 

  对于最小支配集,贪心函数如下:

 

  对于最小点覆盖,贪心函数如下:

 

  对于最大独立集,贪心函数如下:

 

  使用样例:

 

  该方法经过一次深度优先遍历和一次贪心得到最终解,第一步的时间复杂度为O(m),由于这是一棵树,m=n-1.第二步是O(n),总的是O(n)。

  二.树形动态规划法

  仍以最小支配集为例

  基本算法:

  由于这是在树上求最值的问题,显然可以用树形动态规划,只是状态的设计比较复杂。为了保证动态规划的正确性,对于每个点设计了三种状态,这三种状态的意义如下:

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

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

  ③dp[i][2]:i不属于支配集,且以i为根的子树都被覆盖,且i没被子节点覆盖的情况下支配集中所包含最少点的个数。

  对于第一种状态,dp[i][0]等于每个儿子节点的3种状态(其儿子是否被覆盖没有关系)的最小值之和加1,即只要每个以i的儿子为根的子树都被覆盖,再加上当前点i,所需要的最少点的个数,方程如下:

  dp[i][0]=1+Σmin(dp[u][0],dp[u][1],dp[u][2])(p[u]=i).

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

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

  else dp[i][1]=Σmin(dp[u][0],dp[u][1])+inc

  其中对于inc有:

  if(上面式子中的Σmin(dp[u][0],dp[u][1])中包含某个dp[u][0])inc=0;

  else inc=min(dp[u][0]-dp[u][1])。

  对于第三种状态,i不属于支配集,且以i为根的子树都被覆盖,又i没被子节点覆盖,那么说明点i和点i的儿子节点都不属于支配集,则点i的第三种状态只与其儿子的第二种状态有关,方程为

  dp[i][2]=Σdp[u][1]

  对于最小的覆盖问题,为每个点设计了两种状态,这两种状态的意义如下:

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

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

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

  dp[i][0]=1+Σmin(dp[u][0],dp[u][1])(p[u]=i).

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

  dp[i][1]=Σdp[u][0]

  对于最大独立集问题,为每个节点设立两种状态,这两种状态的意义如下:

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

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

  对于第一种状态dp[i][0],由于点i属于独立集,他的子节点都不能属于独立集,所以只与第二种状态有关。方程如下:

  dp[i][0]=1+Σdp[u][1]

  对于第二种状态,点i的子节点可以属于独立集,也可以不属于独立集,方程如下:

  dp[i][1]=Σmax(dp[u][0],dp[u][1])

  具体代码如下:

  u表示当前正在处理的节点,p表示u的父节点。

  最小支配集:

 

  最小点覆盖:

 1 void DP(int u,int p)
 2 {
 3     dp[u][0]=1;
 4     dp[u][1]=0;
 5     int k,to;
 6     for(k=head[u];k!=-1;k=edge[k].next)
 7     {
 8         to=edge[k].to;
 9         if(to==p)continue;
10         DP(to,u);
11         dp[u][0]+=min(dp[to][0],dp[to][1]);
12         dp[u][1]+=dp[to][0];
13     }
14 }

  最大独立集:

 

  由于求的是每个点分别在几种状态下的最优值,所以需要比较dp[root][0],dp[root][1]的值,取较优的一个作为最终答案。

  由于使用的是树状动态规划,所以整个算法的时间复杂度是O(n)。

注:本博客转自此处.

原文地址:https://www.cnblogs.com/Kv-Stalin/p/9096252.html

时间: 2024-10-03 02:23:02

树的最小支配集 最小点覆盖 与 最大独立集 (图论)的相关文章

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

定义: 最小支配集:对于图G = (V, E) 来说,最小支配集指的是从 V 中取尽量少的点组成一个集合, 使得 V 中剩余的点都与取出来的点有边相连.也就是说,设 V' 是图的一个支配集,则对于图中的任意一个顶点 u ,要么属于集合 V', 要么与 V' 中的顶点相邻. 在 V' 中除去任何元素后 V' 不再是支配集, 则支配集 V' 是极小支配集.称G 的所有支配集中顶点个数最少的支配集为最小支配集,最小支配集中的顶点个数称为支配数. 最小点覆盖:对于图G = (V, E) 来说,最小点覆盖

【POJ3659】【USACO 2008 Jan Gold】 3.Cell Phone Network 树上最小支配集/贪心 两种做法

题意:求树上最小支配集 最小支配集:点集,即每个点可以"支配"到相邻点,求最少点数可以使所有点被支配. 图上的最小支配集是NP的,但是树上的可以DP做,是O(n)的. 暴力做就好了, f[i]表示此 点被选时的子树全支配的最小代价 g[i]表示其父亲节 点被选时的子树全支配的最小代价 h[i]表示其某子节 点被选时的子树全支配的最小代价 然后暴力转移. (v是子节点) f[x]=∑(min(f[v],min(g[v],h[v])))+1; g[x]=∑(min(f[v],h[v]));

树的问题小结(最小生成树、次小生成树、最小树形图、LCA、最小支配集、最小点覆盖、最大独立集)

树的定义:连通无回路的无向图是一棵树. 有关树的问题: 1.最小生成树. 2.次小生成树. 3.有向图的最小树形图. 4.LCA(树上两点的最近公共祖先). 5.树的最小支配集.最小点覆盖.最大独立集. 一.最小生成树 解决的问题是:求无向图中边权值之和最小的生成树. 算法有Kruskal和Prim. Kruskal使用前向星和并查集实现,可以存储重边(平行边),时间复杂度是O(m log m  +  m),m是边的数量. Prim使用邻接矩阵建图,不可以存储重边(平行边),如果出现重边,存储的

树的最小支配集,最小点覆盖,最大独立集两种算法

1.基本概念 对图G=<V,E>, 最小支配集:从V中取尽量少的点组成一个集合,使得V中剩余的点都与取出来的点有边相连 最小点覆盖:从V中取尽量少的点组成一个集合,使得E中所有边都与取出来的点相连 最大独立集:从V中取尽量多的点组成一个集合,使得这些点之间没有边相连 2.贪心法求树的最小支配集,最小点覆盖,最大独立集模板 基本算法: 以最小支配集为例,首先选择一点为根,按照深度优先遍历得到遍历序列,按照所得序列的反向序列的顺序进行贪心,对于一个既不属于支配集也不与支配集中的点相连的点来说,如果

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

最小支配集:指从所有顶点中取尽量少的点组成一个集合,使得剩下的所有点都与取出来的点有边相连.顶点个数最小的支配集被称为最小支配集.这里用贪心法来求. 1.以1号点深度优先搜索整棵树,求出每个点在DFS中的编号和每个点的父亲节点编号. 2.按DFS的反向序列检查,如果当前点既不属于支配集也不与支配集中的点相连,且它的父亲也不属于支配集,将其父亲点加入支配集,支配集个数加1. 3.标记当前结点.当前结点的父节点(属于支配集).当前结点的父节点的父节点(与支配集中的点相连). #include<ios

树形DP 树的最小支配集,最小点覆盖与最大独立集

最小支配集: 从V中选取尽量少的点组成一个集合,让V中剩余的点都与取出来的点有边相连. (点) 最小点覆盖: 从V中选取尽量少的点组成一个集合V1,让所有边(u,v)中要么u属于V1,要么v属于V1 (边) 最大独立集: 从V中选取尽量多的点组成一个集合,让这些点中间没有边项链,也就是说对于任何一条边,u,v不能同时属于集合V1. 1.贪心算法 首先选取一个点为根节点,求出所有节点对应的DFS序列,按照所得序列反向进行贪心,这样保证对于每个点来说,当子树都被处理过之后才会处理该节点 int p[

POJ3659 Cell Phone Network(树上最小支配集:树型DP)

题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. 树上的每个结点作为其子树的根可以有三个状态: 不属于支配集且还没被支配 不属于支配集但被其孩子支配 属于支配集 那么就是用dp[u][1\2\3]来表示动归的状态. 123转移该怎么转移就怎么转移..最后的结果就是min(dp[root][2],dp[root][3]). 要注意的是对于有些结点前2

POJ 3659 Cell Phone Network(树的最小支配集)(贪心)

Cell Phone Network Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6781   Accepted: 2429 Description Farmer John has decided to give each of his cows a cell phone in hopes to encourage their social interaction. This, however, requires hi

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

题目链接:https://vjudge.net/problem/UVA-1218 题目大意:给你一棵无向树,让你求树的最小支配集,但是有一个要求是除最小支配集外剩下的任何一个结点不能同时连接支配集中的两个元素 解题报告:采用树形dp,只需将第一种状态的状态转移方程修改为$dp[i][0] = 1+\sum_{ p[u]=i }min(dp[u][0],dp[u][2])$ AC代码: 1 #include<vector> 2 #include<cstdio> 3 #include&