//题意:给定一张图,求最大团顶点数
注:
团:完全图(即每个点和其他各点间都有一条边)。
极大团:在给定的一张图中,若有一个团,在加入该团外任意一点后都不再是一个团,那么该团为极大团。
最大团:给定一张图,其中顶点个数最多的极大团就是最大团。
//思路:最大团模板(dp剪枝)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
#include <string>
#include <cstdlib>
#include <algorithm>
using namespace std;
int n;
int map[60][60];
int Set[60]; //存放点的编号
int Ans; //最大团的顶点数
int dp[60]; //dp用来剪枝
//判断:该点是否和end之前保存在Set中的各点都相连
bool judge(int end, int point)
{
int i;
for (i = 1; i < end; i++)
{
if (!map[Set[i]][point])
return false;
}
return true;
}
//depth:深度(也可以理解为顶点的个数) now:当前点的编号
void dfs(int depth, int now)
{
//剪枝:如果(团中当前顶点个数+当前加入的点到最后(n)的点的个数(n-now+1))比(现存的Ans)还小的话就剪掉
if (depth + n - now + 1 <= Ans || depth + dp[now] <= Ans)
return;
//从now判断到n
//如果该点能和该点之前保存在Set中的点构成团,就dfs它下一个点(递归)
for (int i = now; i <= n; i++)
{
if (judge(depth + 1, i))
{
Set[depth + 1] = i;
dfs(depth + 1, i + 1);
}
}
//更新最大团顶点数
if (depth > Ans)
Ans = depth;
}
int main()
{
int i, j;
while (cin >> n&&n) //n==0 break
{
for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
cin >> map[i][j];
}
}
//max_clique(最大团)
//dp剪枝
memset(dp, 0, sizeof(dp));
Ans = 0;
dp[n] = 1;
for (i = n - 1; i >= 1; i--)
{
Set[1] = i;
dfs(1, i + 1);
dp[i] = Ans;
}
cout << dp[1] << endl;
}
return 0;
}