最大独立集求解

定义:

独立集:在一个图中,找到一个集合包含的所有点相互之间都不存在连边

最大独立集:在所有独立集中包含元素个数最多的独立集

之前只是知道二分图的最大独立集 = 总点数-最大匹配数

但是一般无向图的情况下求解就不能这样了

换个角度思考,其实求最大独立集也是相当于建立一个相反图(把当前的边都去掉,添加上之前不被选中的边)

就变成求修改之后的最大完全图的点的个数了,因为我们要保证选到的点之间不存在任何相连的边,那么图反过来之后,选到的点两两之间就必然

存在边,否则说明之前的图是存在边的,也就是两个点不能全选中,而这样得到的就是完全图

而我们求点数最多的那个,也就是最大完全图,也即最大团

最近学习了一下这类问题的求解方式,这可以看做是一类搜索问题,不断dfs搜索找到最优解

这样很容易看出 这是一个NP问题,复杂度也是 O(2^n)的

所以优秀的剪枝是非常必要的

定义dp[i] 是 i ~ N 这些点所能构成的最大团的点数

那么我们就可以倒过来逐个算出dp[]值

对于前面的dp[]值就要利用之前算出来的值来剪枝

我们这里一个个从小到大添加节点,保证从当前出发添加进来的节点dp值已经求得

例如当前添加了 v , 之前有了 t 个点了

那么就可以用

t+dp[v] <=mx

t+N-t+1<=mx

来剪枝了(这个仔细想一下就知道了)

我们用一个_stack[][]数组记录能够扩展的节点,也就是这个数组中的点和之前取到的点每一个都存在连边,所以添加进来可以直接构成完全图

我们只要每次再添加节点后更新这个数组就可以了

因为是递归求解了,防止更新了会在回溯时出错,那么就讲数组定成两维的,第一维表示当前集合最大的点就可以直接用了

int cnt = 0;
for(int j=i+1 ; j<num ; j++){
  if(!mp[v][_stack[u][j]]) _stack[v][cnt++] = _stack[u][j];
}

然后POJ1419就是一道这个的裸题,只是每次记录了最优解要取到的点而已

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 #define N 105
 6 bool mp[N][N];
 7 int T , n , k;
 8 int dp[N] , ans[N] , tmp[N] , ret , mx , cnt;
 9 int _stack[N][N];
10
11 void build(int k)
12 {
13     memset(mp , 0 , sizeof(mp));
14     for(int i=1 ; i<=n ; i++) mp[i][i] = true;
15     for(int i=0 ; i<k ; i++){
16         int a , b;
17         scanf("%d%d" , &a , &b);
18         mp[a][b] = true;
19     }
20 }
21
22 void dfs(int u , int num , int step)
23 {
24     if(num == 0){
25         if(mx<step){
26             mx = step;
27             if(step>ret) for(int i=1 ; i<=step ; i++) ans[i] = tmp[i];
28         }
29         return;
30     }
31
32     for(int i=0 ; i<num ; i++){
33         int v = _stack[u][i];
34         //two methods of cut the node
35         if(step+dp[v]<=mx) continue;
36         if(step+n-v+1<=mx) continue;
37         //从stack中能访问到v说明,v和之前所有点都有连边的,只要重新更新stack中的数据就可以了
38         int cnt = 0;
39         for(int j=i+1 ; j<num ; j++){
40             if(!mp[v][_stack[u][j]]) _stack[v][cnt++] = _stack[u][j];
41         }
42         tmp[step+1] = v;
43         dfs(v , cnt , step+1);
44     }
45 }
46
47 int main()
48 {
49   //  freopen("a.in" , "r" , stdin);
50     scanf("%d" , &T);
51     while(T--){
52         scanf("%d%d" , &n , &k);
53         build(k);
54         ret = 0; //init
55         for(int i=n ; i>=1 ; i--){
56             cnt = 0 , mx = 1;
57             for(int j=i+1 ; j<=n ; j++){
58                 if(!mp[i][j]) _stack[i][cnt++] = j;
59             }
60             tmp[1] = i;
61             dfs(i , cnt , 1);
62             dp[i] = mx;
63             ret = max(ret , dp[i]);
64         }
65         printf("%d\n" , ret);
66         for(int i=1 ; i<=ret ; i++){
67             if(i<ret) printf("%d " , ans[i]);
68             else printf("%d\n" , ans[i]);
69         }
70     }
71     return 0;
72 }
时间: 2024-11-12 14:20:26

最大独立集求解的相关文章

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

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

hihocoder 1158 质数相关 (二分图最大独立集 最大流ISAP求解)

#1158 : 质数相关 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 两个数a和 b (a<b)被称为质数相关,是指a × p = b,这里p是一个质数.一个集合S被称为质数相关,是指S中存在两个质数相关的数,否则称S为质数无关.如{2, 8, 17}质数无关,但{2, 8, 16}, {3, 6}质数相关.现在给定一个集合S,问S的所有质数无关子集中,最大的子集的大小. 输入 第一行为一个数T,为数据组数.之后每组数据包含两行. 第一行为N,为集合S的大小.第二

POJ 1466 Girls and Boys 黑白染色 + 二分匹配 (最大独立集) 好题

有n个人, 其中有男生和女生,接着有n行,分别给出了每一个人暗恋的对象(不止暗恋一个) 现在要从这n个人中找出一个最大集合,满足这个集合中的任意2个人,都没有暗恋这种关系. 输出集合的元素个数. 刚开始想,把人看成顶点,若有暗恋的关系,就连一条边,构成一个图 独立集的概念:一个图中两两互不相连的顶点集合 所以这道题,就是要求最大独立集 有:最大独立集+最小顶点覆盖=|V|(顶点的总个数) 那就求最小顶点覆盖了 根据题意: 暗恋的对象性别不同,所以a暗恋b,b暗恋c,c暗恋a这种关系不可能存在 也

最大匹配、最小顶点覆盖、最大独立集、最小路径覆盖(转)

在讲述这两个算法之前,首先有几个概念需要明白: 二分图: 二分图又称二部图,是图论中的一种特殊模型.设G=(V,E)是一个无向图,如果顶点V可以分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A, j in B), 则称图G是二分图. 匹配: 给定一个二分图,在G的一个子图G'中,如果G'的边集中的任意两条边都不依附于同一个顶点,则称G'的边集为G的一个匹配 最大匹配: 在所有的匹配中,边数最多的那个匹配就是二分图的最大匹

【BZOJ-4316】小C的独立集 仙人掌DP + 最大独立集

4316: 小C的独立集 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 57  Solved: 41[Submit][Status][Discuss] Description 图论小王子小C经常虐菜,特别是在图论方面,经常把小D虐得很惨很惨. 这不,小C让小D去求一个无向图的最大独立集,通俗地讲就是:在无向图中选出若干个点,这些点互相没有边连接,并使取出的点尽量多. 小D虽然图论很弱,但是也知道无向图最大独立集是npc,但是小C很仁慈的给了一个很

POJ 1466 Girls and Boys (匈牙利算法 最大独立集)

Girls and Boys Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 10912   Accepted: 4887 Description In the second year of the university somebody started a study on the romantic relations between the students. The relation "romantically in

二分图最大匹配,最小路径覆盖,最小点覆盖,最大独立集,最小边覆盖与建图方法

转载请注明出处(别管写的好坏,码字也不容易):http://blog.csdn.net/hitwhacmer1 前言:         有自己写的,有摘的别人的,前面是摘的,也是无心整理,出错是难免的,反正我都不会证明,智人见智,别被我误导了. §1图论点.边集和二分图的相关概念和性质 点覆盖.最小点覆盖 点覆盖集即一个点集,使得所有边至少有一个端点在集合里.或者说是"点" 覆盖了所有"边"..极小点覆盖(minimal vertex covering):本身为点覆

HDU 3829 - Cat VS Dog (二分图最大独立集)

题意:动物园有n只猫和m条狗,现在有p个小孩,他们有的喜欢猫,有的喜欢狗,其中喜欢猫的一定不喜欢狗,喜欢狗的一定不喜欢猫.现在管理员要从动物园中移除一些动物,如果一个小孩喜欢的动物留了下来而不喜欢的动物被移走,这个小孩会很高兴.现在问最多可以让多少个小孩高兴. 此题是求二分图最大独立集. 二分图比较明显,但是难在建图.这个题是找到最多的喜欢猫和喜欢狗而不互相冲突的小孩,这样我们将喜欢动物相互冲突的小孩之间连边,问题就变成了求二分图的最大独立集. 在二分图中,最大独立集=顶点数-最大匹配数. 求解

POJ 3342 Party at Hali-Bula (树形dp 树的最大独立集 判多解 好题)

Party at Hali-Bula Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5660   Accepted: 2022 Description Dear Contestant, I'm going to have a party at my villa at Hali-Bula to celebrate my retirement from BCM. I wish I could invite all my co