0
点赞
收藏
分享

微信扫一扫

对最大团的理解

定义: 
    最大团就是给你一个图,让你在这个图里面找到一个最大的子图,这个子图必须是全图,最大的子图就是这个图的最大团。


算法:
      首先最大团是NP问题,没有什么非常快的方法去解决,现在可以用搜索+剪枝去尽可能的快速处理最大团问题,其中一个很重要的剪枝就是如果当前集合的顶点数+剩下所有的点<当前全局的最优答案,那么直接return,不然搜下去也没意义,我们要枚举每一个团,找到最大的那个,对于当前点,如果满足要求(和当前团所有点都有连边)那么他可以加入团或者放弃,如果满足要求,直接放弃,一直枚举,更新最优就行了。
接着补充一下,经过做3585的那个二分最大团发现自己写的模板各种超时,超时到蛋疼,最后学了下dp优化的,然后就过了,dp优化的理解是这样的,对于dp优化首先我们要知道如果这样的写法


枚举第一个点的时候for(int i = n - 1 ;i >= 1 ;i --)
DFS里面跑的时候for(int i = x + 1 ;i <= n ;i ++)
这样就导致每次DFS是比上次增加了一个节点,对于当前点的本次搜索索要面临的点都已经被枚举过了,然后当前这个点加入如果是"有效"的,那么他肯定是之前的某一个团+1,如果当前的这个点要走的点+要走的那个点的之前最大团还是没有当前全局答案大,那么就没有必要遍历了,直接就continue就行了。


//*******************************
最大团:图G的顶点的子集D,若D中任意两点相邻,且含有的顶点数最大,则D为最大团。
        因此若u,v在最大团中,则u,v必有边相连
        一个有N个顶点的最大团,边数为N*(N-1)/2
求最大团是NP问题,常用的方法是DP优化+ DFS
 
与之相关的概念是最大独立集:
独立集是指图的顶点集的一个子集,该子集的导出子图不含边。
一个图中包含顶点数目最多的独立集称为最大独立集。
所以最大独立子集=图的补图的最大团
//***********************************


自己写的一个模板(容易超时)


#include<stdio.h>



#define N 60



int map[N][N] ,n;

int now[N] ,Ans;



bool ok(int sum ,int to)

{

for(int i = 1 ;i <= sum ;i ++)

if(!map[now[i]][to]) return 0;

return 1;

}



void DFS(int to ,int sum ,int node)

{

if(Ans < sum) Ans = sum;

if(sum + n - node < Ans) return;

for(int i = to + 1 ;i <= n ;i ++)

if(ok(sum ,i))

{

now[sum + 1] = i;

DFS(i ,sum + 1 ,node + 1);

}

}



int main ()

{

int i ,j;

while(~scanf("%d" ,&n) && n)

{

for(i = 1 ;i <= n ;i ++)

for(j = 1 ;j <= n ;j ++)

scanf("%d" ,&map[i][j]);

Ans = 0;

for(i = 1 ;i <= n ;i ++)

{

now[1] = i;

DFS(i ,1 ,1);

}

printf("%d\n" ,Ans);

}

return 0;

}



dp优化的(目前比较快的)

#include<stdio.h>



#define N 60



int map[N][N];

int dp[N] ,now[N];

int n ,Ans;



void DFS(int x ,int sum)

{

if(sum > Ans) Ans = sum;



int able = 0;

int tnow[N];

for(int i = x + 1 ;i <= n ;i ++)

{

tnow[i] = now[i];

if(now[i]) able ++;

}

if(able + sum <= Ans) return;



for(int i = x + 1 ;i <= n ;i ++)

{

if(!tnow[i]) continue;

if(dp[i] + sum <= Ans) return;

for(int j = x + 1 ;j <= n ;j ++)

now[j] = tnow[j] & map[i][j];

DFS(i ,sum + 1);

}

}



int Max_Tuan()

{

Ans = dp[n] = 1;

for(int i = n - 1 ;i >= 1 ;i --)

{

for(int j = 1 ;j <= n ;j ++)

now[j] = map[i][j];

DFS(i ,1);

dp[i] = Ans;

}

return Ans;

}



int main ()

{

int i ,j;

while(~scanf("%d" ,&n) && n)

{

for(i = 1 ;i <= n ;i ++)

for(j = 1 ;j <= n ;j ++)

scanf("%d" ,&map[i][j]);

printf("%d\n" ,Max_Tuan());

}

return 0;

}


   








      



举报

相关推荐

0 条评论