https://codeforc.es/contest/1105/problem/E
最大团==补图的最大独立集
此题求的是最大独立集数 等效为补图的最大团
最大团模板:参考https://blog.csdn.net/qq_33951440/article/details/78154625
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define FI first
#define SE second
#define MP make_pair
#define PII pair<int,int>
const LL mod =1e9+7;
const int N = 50;
bool a[N][N];//a为图的邻接表(从1开始)
int ans, cnt[N], group[N], n, m, vis[N];
bool dfs(int u,int pos){ //u为当从前顶点开始深搜,pos为深搜深度(即当前深搜树所在第几层的位置)
int i,j;
for(i=u+1;i<=n;i++){ //按递增顺序枚举顶点
if(cnt[i]+pos<=ans) return 0;//剪枝
if(a[u][i]){ // 与目前团中元素比较,取 Non-N(i)
for(j=0;j<pos;j++) if(!a[i][vis[j]]) break;
if(j==pos) {// 若为空,则皆与 i 相邻,则此时将i加入到 最大团中
vis[pos]=i;//深搜层次也就是最大团的顶点数目,vis[pos] = i表示当前第pos小的最大团元素为i(因为是按增顺序枚举顶点 )
if(dfs(i,pos+1)) return 1;
}
}
}
if(pos>ans){
for(i=0;i<pos;i++) group[i]=vis[i]; // 更新最大团元素
ans=pos;
return 1;
}
return 0;
}
void maxclique(){ //求最大团
ans=-1;
for(int i=n;i>0;i--){
vis[0]=i;
dfs(i,1);
cnt[i]=ans;
}
}
map<string,int>ma;
vector<int>v;int cc=1;
int main(){
cin>>m>>n;
/* 建图 */
for(int i=1;i<=m;i++){
int op;scanf("%d",&op);
if(op==1){
v.clear();
}
else {
string s;cin>>s;
if(ma.find(s)==ma.end())ma[s]=cc++;
v.push_back(ma[s]);
for(int j=0;j<(int)v.size()-1;j++){
a[v[v.size()-1]][v[j]]=1;
a[v[j]][v[v.size()-1]]=1;
}
}
}
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(i!=j)a[i][j]^=1;
/* 建图 */
maxclique();
if(ans<0)ans=0;//ans小于0
cout<<ans;
return 0;
}
最大团数量模板:参考:https://blog.csdn.net/yo_bc/article/details/77453478
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 130;
bool mp[maxn][maxn];
int some[maxn][maxn], none[maxn][maxn], all[maxn][maxn];
int n, m, ans;
void dfs(int d, int an, int sn, int nn)
{
if(!sn && !nn) ++ans;
int u = some[d][0];
for(int i = 0; i < sn; ++i)
{
int v = some[d][i];
if(mp[u][v]) continue;
for(int j = 0; j < an; ++j)
all[d+1][j] = all[d][j];
all[d+1][an] = v;
int tsn = 0, tnn = 0;
for(int j = 0; j < sn; ++j)
if(mp[v][some[d][j]])
some[d+1][tsn++] = some[d][j];
for(int j = 0; j < nn; ++j)
if(mp[v][none[d][j]])
none[d+1][tnn++] = none[d][j];
dfs(d+1, an+1, tsn, tnn);
some[d][i] = 0, none[d][nn++] = v;
if(ans > 1000) return;
}
}
int work()
{
ans = 0;
for(int i = 0; i < n; ++i) some[1][i] = i+1;
dfs(1, 0, n, 0);
return ans;
}
int main()
{
while(~scanf("%d %d", &n, &m))
{
memset(mp, 0, sizeof mp);
for(int i = 1; i <= m; ++i)
{
int u, v;
scanf("%d %d", &u, &v);
mp[u][v] = mp[v][u] = 1;
}
int tmp = work();
if(tmp > 1000) puts("Too many maximal sets of friends.");
else printf("%d\n", tmp);
}
return 0;
}