最大团问题

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);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值