题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1530
题意:
求一个图的最大完全子图
算法:
最大团算法。这是一个NP问题,所以解法是搜索+剪枝
我借鉴了http://blog.youkuaiyun.com/leolin_/article/details/7251962 的模板
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
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;
}
这篇博客介绍了如何解决HDOJ 1530问题,即寻找图的最大完全子图。作者提到这是一个NP问题,并采用最大团算法结合搜索和剪枝策略来求解。博客提供了相关算法的思路和代码实现,参考了其他资源进行优化。
333

被折叠的 条评论
为什么被折叠?



