maximum clique 最大团

最大团模板

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#define out(v) cout << #v << ": " << (v) << endl
#define MP(X,Y) make_pair(X,Y)
using namespace std;
typedef long long LL;

// maximum clique
// tested: hdu3585, zju1492, pku1129
// paper: A Fast Algorithm For The Maximum Clique Problem
const int MAXN = 27;
int n;
bool G[MAXN][MAXN]; // indexed from one, adjacency matrix
int list[MAXN][MAXN], degree[MAXN], behide[MAXN];
int found, curmax;

void sortdegree() {
for (int i = 1; i <= n; i++) {
int k = i;
for (int j = i + 1; j <= n; j++)
if (degree[j] < degree[k]) k = j;
if (k != i) {
swap(degree[i], degree[k]);
for (int t = 1; t <= n; t++) swap(G[i][t], G[k][t]);
for (int t = 1; t <= n; t++) swap(G[t][i], G[t][k]);
}
}
}
void dfs(int d){
if (d - 1 > curmax) { found = 1; return; };
int i, j;
for (int i = 1; i < list[d - 1][0] - curmax + d; i++)
if (!found && d + behide[list[d - 1][i] + 1] > curmax
&& (list[d - 1][0] == i || d + behide[list[d - 1][i + 1]] > curmax)) {
for (j = i + 1, list[d][0] = 0; j <= list[d - 1][0]; j++)
if (G[list[d - 1][j]][list[d - 1][i]])
list[d][++list[d][0]] = list[d - 1][j];
if (list[d][0] == 0 || d + behide[list[d][1]] > curmax)
dfs(d + 1);
}
}
int solve() {
for (int i = 1; i <= n; i++) {
degree[i] = 0;
for (int j = 1; j <= n; j++) degree[i] += G[i][j];
}
sortdegree(); behide[n + 1] = 0; behide[n] = 1;
for (int i = n - 1; i > 0; i--) {
curmax = behide[i + 1]; found = list[1][0] = 0;
for (int j = i + 1; j <= n; j++)
if (G[j][i]) list[1][++list[1][0]] = j;
dfs(2); behide[i] = curmax + found;
}
return behide[1];
}

int set[MAXN];
int main()
{
char line[30];
while (scanf("%d", &n), n != 0)
{
memset(G, false, sizeof(G));
for (int i = 1; i <= n; ++i)
{
scanf("%s", line);
int u = line[0] - 'A' + 1;
set[i] = u;
for (int j = 2; line[j]; ++j)
G[u][line[j] - 'A' + 1] = true;
}
int cnt = solve();
printf("%d channel%s needed.\n", cnt, cnt == 1 ? "" : "s");
for (int i = 1; i <= list[1][0]; ++i)
cout << char('A' + list[1][i] - 1) << " ";
cout << endl;
}

return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值