HDOJ 1530: Maximum Clique

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1530


题意:

求一个图的最大完全子图


算法:

最大团算法。这是一个NP问题,所以解法是搜索+剪枝

我借鉴了http://blog.csdn.net/leolin_/article/details/7251962 的模板


代码:

#include 
#include 
#include 
#include 
using namespace std;

const int maxn = 60;
int mx; //最大团数
int x[maxn], clique[maxn];
int can[maxn][maxn]; //表示在已经确定了经选定的i个点必须在最大团内的前提下还有可能被加进最大团的结点集合
int num[maxn]; //num[i]表示由结点i到结点n构成的最大团的结点数
bool mm[maxn][maxn];

bool dfs(int tot, int cnt)
{
    if(tot == 0)
    {
        if(cnt > mx)
        {
            mx = cnt;
            for(int i = 0; i < mx; i ++)
            {
                clique[i] = x[i];
            }
            return true;

        }
        return false;

    }
    for(int i = 0; i < tot; i ++)
    {
        if(cnt + (tot - i) <= mx)
        {
            return false;
        }
        if(cnt + num[can[cnt][i]] <= mx)
        {
            return false;
        }
        int k = 0;
        x[cnt] = can[cnt][i];
        for (int j = i + 1; j < tot; j ++)
        {
            if(mm[can[cnt][i]][can[cnt][j]])
            {
                can[cnt + 1][k ++] = can[cnt][j];

            }
        }
        if(dfs(k, cnt + 1))
        {
            return false;
        }
    }
    return false;
}

void maxClique(int n)
{
    mx = 1;
    for(int i = n - 1; i >= 0 ; i --)
    {
        int k = 0;
        x[0] = i;
        for(int j = i + 1; j < n; j ++)
        {
            if(mm[i][j])
            {
                can[1][k ++] = j;

            }
        }
        dfs(k, 1);
        num[i] = mx;

    }
}

int main()
{
    int n;
    while (scanf("%d", &n) == 1 && n)
    {
        for (int i = 0; i < n; i ++)
        {
            for (int j = 0; j < n; j ++)
            {
                scanf("%d", &mm[i][j]);
            }
        }
        maxClique(n);
        printf("%d\n", mx);
    }
    return 0;
}


你可能感兴趣的:(ACM_图论)