首先来看一下这三个知识点的概念
一、最小支配集
对于图G=(V,E)来说,最小支配集指的是从V中取尽量少的点组成一个集合,使得对于V中剩余的点都与取出来的点有边相连。也就是说,设V‘是图G的一个支配集,则对于图中的任意一个顶点u,要么属于集合V’,要么与V‘中的顶点相邻。在V’中出去任何元素后V‘不再是支配集,则支配集是极小支配集。称G的所有支配集中顶点个数最少的支配集为最小支配集,最小支配集中顶点的个数称为支配数。
二、最小点覆盖
对于图G=(V,E)来说,最小点覆盖指的是从V中取尽量少的点组成一个集合,使得E中所有的边都与取出来的点相连。也就是说,设V‘是图G的一个顶点覆盖,则对于图中的任意一条边(u,v),要么u属于集合V’,要么v属于集合V‘。在V‘中除去任何元素后V’不在是顶点覆盖,则V‘是极小顶点覆盖。称G的所有顶点覆盖中顶点个数最少的覆盖为最小点覆盖。
三、最大独立集
对于图G=(V,E)来说,最大独立集指的是从V中取尽量多的点组成一个集合,使得这些点之间没有边相连。也就是说,设V’是图G的一个独立集,则对于图中任意一条边(u,v),u和v不能同时属于集合V',甚至可以u和v都不属于集合V‘。在V’中添加任何不属于V‘元素后V’不再是独立集,则V‘是极大独立集。称G的所有顶点独立集中顶点个数最多的独立集为最大独立集。
自我感觉最小点覆盖和最小支配集容易弄混......第一次做题时就把最小支配集当成最小点覆盖做了...orz
最小支配集处理的是点,最小点覆盖处理的是边
要记住最小点覆盖在贪心的时候是不处理根节点的。
接下来是贪心处理
无论哪一个都是先深搜一遍得到遍历序列,然后倒着处理。
倒着处理使得每一个节点都是处理完了它的所有子节点后再来处理它,保证了贪心的正确性
最小支配集:
倒着遍历的时候,如果当前点既不属于支配集也没有被支配集里的点相连(即没有被覆盖),并且它的父节点也没有在支配集里,就将它的父节点加入到支配集里,ans++,将当前点,当前点的父节点,当前点的父节点的父节点标记(被覆盖了)
int p[N]; //父节点编号
int newpos[N]; //深度优先遍历中newpos[i]=x为编号为x的点是第i个被遍历的
bool vis[n]; //是否已经遍历过
int now; //现在已经有几个点被遍历
int n,m;
void dfs(int x) //搜索
{
newpos[++now]=x;
f