首先我们来看一下问题
先码在下面
我们知道回溯法一般生成子集树和排列树,在这个问题中我们很容易得知我们要解决的问题是一个子集树,因为每个公民要么去要么不去,首先我们得找出可行解,当递归到了叶子节点的时候我们计算并更新最优值
#include <iostream>
#include <time.h>
using namespace std;
int maxc=0;//定义最优人数
int n;//居民人数
int m;//m对仇敌关系
int x[51][51]={0};//邻接矩阵
int rest=0;//剩余可选人数
int cur=0;//当前已选人数
int check(int t,int c[]){
for (int i = 1; i <t ; ++i)
{ //检查当前加进来的第t个村民是否和之前的居民存在仇敌关系
if(c[i]){
if(x[i][t]){
return 0;
}
}
}
return 1;}
void traceback(int t,int c[]){
if (t>n)
{
int temp=0;
for (int i = 1; i < n+1; ++i)
{
temp+=c[i];
}
if (temp>maxc)
{
maxc=temp;
}
return ;
}
rest--;
if (check(t,c))//限制函数
{ cur++;//当前已选人数
c[t]=1;//第t个居民被选择
traceback(t+1,c);
c[t]=0;
cur--;
}
if ((rest+cur)>maxc)//限界函数
{
traceback(t+1,c);
}
rest++;
}
int main()
{
cin>>n>>m;
rest=n;//最开始剩余价值是最多的 也就是所有居民都能选
int c[m+1]={0};//下标0做占位用 方便下标从1开始访问 赋值为0代表未选
for(int i=0;i<m;i++){
int a,b;
cin>>a>>b;
x[a][b]=1;
x[b][a]=1;
}
traceback(1,c);
cout<<maxc;
}
测试结果: