树的最小支配集,最小点覆盖与最大独立集
2016-03-06 15:15
393 查看
首先看一下三者的定义:
定义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来说,这三个问题不存在多项式时间的解法。 不过对于树来说,却很容易。目前有两种解法,一种基于贪心思想,另一种基于树形动态规划思想。
View Code
对于最小支配集,贪心函数如下:
View Code
对于最小点覆盖,贪心函数如下:
View Code
对于最大独立集,贪心函数如下:
定义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来说,这三个问题不存在多项式时间的解法。 不过对于树来说,却很容易。目前有两种解法,一种基于贪心思想,另一种基于树形动态规划思想。
求解(贪心算法):对整棵树进行dfs,求出dfs序,然后进行贪心。以求支配集为例,对于儿子和父亲,肯定选父亲能影响到的更多,那么只要把最小面一层确定后就可以从后往前进行判断了。
1 int p[maxn]; 2 bool select[maxn]; 3 int newpos[maxn]; 4 int now; 5 int n,m; 6 void DFS(int x) 7 { 8 newpos[now++]=x; 9 int k; 10 for(k=head[x];k!=-1;k=edge[k].next) 11 { 12 if(!select[edge[k].to]) 13 { 14 select[edge[k].to]=true; 15 p[edge[k].to]=x; 16 DFS(edge[k].to); 17 } 18 } 19 }
View Code
对于最小支配集,贪心函数如下:
1 int greedy() 2 { 3 bool s[maxn]; 4 bool set[maxn]={0}; 5 int ans=0; 6 int i; 7 for(i=n-1;i>=0;i--) 8 { 9 int t=newpos[i]; 10 if(!s[t]) 11 { 12 if(!set[p[t]]) 13 { 14 set[p[t]]=true; 15 ans++; 16 } 17 s[t]=true; 18 s[p[t]]=true; 19 s[p[p[t]]]=true; 20 } 21 } 22 return ans; 23 }
View Code
对于最小点覆盖,贪心函数如下:
1 int greedy() 2 { 3 bool s[maxn]={0}; 4 bool set[maxn]={0}; 5 int ans=0; 6 int i; 7 for(i=n-1;i>=1;i--) 8 { 9 int t=newpos[i]; 10 if(!s[t]&&s[p[t]]) 11 { 12 set[p[t]]=true; 13 ans++; 14 s[t]=true; 15 s[p[t]]=true; 16 } 17 } 18 return ans; 19 }
View Code
对于最大独立集,贪心函数如下:
1 int greedy() 2 { 3 bool s[maxn]={0}; 4 bool set[maxn]={0}; 5 int ans=0; 6 int i; 7 for(i=n-1;i>=0;i--) 8 { 9 int t=newpos[i]; 10 if(!s[t]) 11 { 12 set[t]=true; 13 ans++; 14 s[t]=true; 15 s[p[t]]=true; 16 } 17 } 18 return ans; 19 }
相关文章推荐
- 斐波那契数列
- 使用jQuery或者原生js实现鼠标滚动加载页面新数据
- linux(ubuntu)sudoers权限错误导致sudo无法使用
- Android 菜鸟认知总结——Android初印象之系统架构和app 组件
- hdoj 1418 抱歉(公式)
- openssl 加密
- Tsinsen-A1103 ====单循环赛制====固定轮转法。。
- 构建之法阅读笔记01
- 几个具体的编辑器类的成员
- java简单操作word实例
- SQL Server 2008还原数据库时出现“备份集中的数据库备份与现有的数据库不同”的解决方法
- JavaScript加载XMl文件
- java中hashCode方法与equals方法的用法总结
- 理解int main(int argc,char **argv)中的参数的意义
- 提问的艺术
- 利用linuxkernel构建一个精简版的操作系统内核
- Linux是如何启动的
- <Android编程权威指南>之1.6 Activity.this和this的区别
- play1.2.7局部编译,局部打包完整解决方案
- 罗列iOS开发中各种的宏定义