子问题定义: 对于图中的每个结点,有两种状态,即属于最小点覆盖和不属于最小点覆盖,定义minSet[i][0]表示结点i属于点覆盖,并且以i为根的树的最小点覆盖的大小。minSet[i][1]表示点i不属于点覆盖,并且以i为根的树的最小点覆盖的大小。
递归关系:
对于minSet[i][0],i的孩子结点可以属于点覆盖,也可以不属于点覆盖,取其使以i为根的子树的点覆盖最小的情况,因此
对于minSet[i][1],由于i不属于点覆盖,因此其所有孩子结点都必须属于点覆盖,因此
初值设定:
minSet[i][0]=1
minSet[i][1]=0
求解顺序:
从树的叶子结点开始求每个结点的最小点覆盖,自底向上,最后比较minSet[root][0]与minSet[root][1]的大小,最小者即为最终的结果。
1 package org.xiu68.ch6.ex8; 2 3 import java.util.ArrayList; 4 5 public class Exp6_21 { 6 7 public static void main(String[] args) { 8 // TODO Auto-generated method stub 9 //运行结果 10 /* 11 树的最大独立集为: 4 12 顶点值为: 4 6 2 3 13 树的最小点覆盖为: 2 14 顶点值为: 5 1 15 */ 16 //由结果可知 最大独立集与最小点覆盖集合互为补集 17 ArrayList<Integer> vexs=new ArrayList<>(); 18 for(int i=1;i<=6;i++) 19 vexs.add(i); 20 //构造一个无向无环图 21 int[][] edges=new int[][]{ 22 {0,1,1,0,0,0}, 23 {1,0,0,0,1,0}, 24 {1,0,0,0,0,0}, 25 {0,0,0,0,1,0}, 26 {0,1,0,1,0,1}, 27 {0,0,0,0,1,0} 28 }; 29 MGraph<Integer> m=new MGraph<Integer>(6, 6, edges, vexs); 30 m.maxIndependentSet(); 31 System.out.println(); 32 m.minCoverSet(); 33 } 34 } 35 36 37 //邻接矩阵表示图、无向无环图 38 class MGraph<T>{ 39 public int vexNum; //顶点数量 40 public int edgeNum; //边数量 41 public int[][] edges; //邻接矩阵 42 public ArrayList<T> vexs; //顶点表 43 44 public int[][] maxDep; //最大独立集 45 public ArrayList<Integer> set; //最大独立集顶点序号 46 47 public int[][] minCover; //最小点覆盖 48 public ArrayList<Integer> minSet; //最小点覆盖顶点序号 49 50 public MGraph(int vexNum, int edgeNum, int[][] edges, ArrayList<T> vexs) { 51 this.vexNum = vexNum; 52 this.edgeNum = edgeNum; 53 this.edges = edges; 54 this.vexs = vexs; 55 56 maxDep=new int[vexNum][2]; 57 set=new ArrayList<>(); 58 59 minCover=new int[vexNum][2]; 60 minSet=new ArrayList<>(); 61 } 62 63 //最大独立集 64 public void maxIndependentSet(){ 65 independentSet(0, 0); 66 67 if(maxDep[0][0]>maxDep[0][1]) 68 System.out.println("树的最大独立集为: "+maxDep[0][0]); 69 else 70 System.out.println("树的最大独立集为: "+maxDep[0][1]); 71 72 System.out.print("顶点值为: "); 73 for(int i=0;i<set.size();i++) 74 System.out.print(vexs.get(set.get(i))+" "); 75 } 76 //求以child为根的树的最大独立集 77 //child:当前正在处理的结点 78 //parent:child的父结点 79 private void independentSet(int child,int parent){ 80 maxDep[child][0]=1; //当前结点放入独立集 81 maxDep[child][1]=0; //当前结点不放入独立集 82 83 for(int i=0;i<vexNum;i++){ 84 if(edges[child][i]==0 || i==parent) //如果顶点间不存在边或尾结点为父结点 85 continue; 86 independentSet(i, child); 87 88 //因为child加入了最大独立集,所以子结点不加入最大独立集 89 //以child为根的树的最大独立集的规模为 ( 1+ child的孙子结点的最大独立集的规模 ) 90 maxDep[child][0]+=maxDep[i][1]; 91 92 if(maxDep[i][0]>maxDep[i][1]) 93 maxDep[child][1]+=maxDep[i][0]; //加入子结点 94 else 95 maxDep[child][1]+=maxDep[i][1]; //不加入子结点 96 } 97 98 if(maxDep[child][0]>maxDep[child][1]) //比较加入child与不加入child的独立集大小,取较大者为结果 99 set.add(child); 100 } 101 102 //*********************************************************** 103 104 //最小点覆盖 105 public void minCoverSet(){ 106 coverSet(0,0); 107 if(minCover[0][0]<minCover[0][1]) 108 System.out.println("树的最小点覆盖为: "+minCover[0][0]); 109 else 110 System.out.println("树的最小点覆盖为: "+minCover[0][1]); 111 112 System.out.print("顶点值为: "); 113 for(int i=0;i<minSet.size();i++){ 114 System.out.print(vexs.get(minSet.get(i))+" "); 115 } 116 } 117 //求以child为根的树的最小点覆盖集合 118 //child:当前正在处理的结点 119 //parent:child的父结点 120 private void coverSet(int child,int parent){ 121 minCover[child][0]=1; //child放入最小点覆盖集合 122 minCover[child][1]=0; //child不放入最小点覆盖集合 123 124 for(int i=0;i<vexNum;i++){ 125 if(edges[child][i]==0 || i==parent) //如果顶点间不存在边或尾结点为父结点 126 continue; 127 128 coverSet(i,child); 129 130 //如果子结点i放入集合结果更小则把i放入集合 131 if(minCover[i][0]<minCover[i][1]) 132 minCover[child][0]+=minCover[i][0]; //子结点i放入集合 133 else 134 minCover[child][0]+=minCover[i][1]; //子结点i不放入集合 135 136 //若child不放入最小点覆盖集合,则其所有子结点都要放入最小点覆盖集合 137 minCover[child][1]+=minCover[i][0]; 138 139 if(minCover[child][0]<minCover[child][1]) //取最小值作为结果 140 minSet.add(child); 141 } 142 } 143 }
时间: 2024-10-13 21:34:01