1. 程式人生 > >樹的最小支配集,最小點覆蓋與最大獨立集

樹的最小支配集,最小點覆蓋與最大獨立集

首先看一下三者的定義:

定義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 }