Description
给定无向图G=(V,E)。如果UV,且对任意u, v ∈ U 有 (u,v) ∈ E,则称U是G的完全子图。G的完全子图U是G的团,当且仅当U不包含在G的更大的完全子图中。G的最大团是指G中所含顶点数最多的团。
Input
输入的第一行为测试样例的个数T ,接下来有T个测试样例。每个测试样例的第一行是 顶点数n 和 边数m ( n ≤ 20,m ≤ 400 ),接下来m行,每行两个整数u和v,表示顶点u和v之间有一条边相连。( 1 ≤ u < v ≤ n )。
Output
对应每个测试样例输出两行,第一行格式为"Case #: M",其中’#'表示第几个测试样例(从1开始计),M为最大团顶点数。
Sample Input
1
5 7
1 2
1 4
1 5
2 3
2 5
3 5
4 5
Sample Output
Case 1: 3
代码入下:
#include<bits/stdc++.h>
using namespace std;
/*
G[] //图
x[] //当前解
bestx[] //最优解
pn //当前顶点数
bestn //当前最大顶点数
*/
void Backtrack(int t,int n);
int G[50][50],bestx[50],x[50];
int pn,bestn;
int main(){
int T,n,m,a,b,z=0;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
memset(G,0,sizeof(G));
for(int i=1;i<=m;i++){
scanf("%d%d",&a,&b);
G[a][b]=1;
G[b][a]=1;
}
pn=bestn=0;
memset(x,0,sizeof(x));
Backtrack(1,n);
printf("Case %d: %d\n",++z,bestn);
}
return 0;
}
void Backtrack(int t,int n){
if(t>n){ //一趟完之后,记录当前最优解
for(int i=1;i<=n;i++){
bestx[i]=x[i];
}
bestn=pn; //记录最优解顶点数
return;
}
int op=1;
for(int i=1;i<t;i++){ //检查i/t是否相连
if(x[i] && G[t][i]==0){ //不相连
op=0;
break;
}
}
if(op){ //相连
x[t]=1; //选点(进入左子树)
pn++;
Backtrack(t+1,n);
x[t]=0; //选点递归回来之后,不选(进入右子树)
pn--;
}
if(pn+n-t>bestn){ //剪枝函数(进入右子树)
x[t]=0;
Backtrack(t+1,n);
}
}