分考场
问题描述
n个人参加某项特殊考试。
为了公平,要求任何两个认识的人不能分在同一个考场。
求是少需要分几个考场才能满足条件。
输入格式
第一行,一个整数n(1<n<100),表示参加考试的人数。
第二行,一个整数m,表示接下来有m行数据
以下m行每行的格式为:两个整数a,b,用空格分开 (1<=a,b<=n) 表示第a个人与第b个人认识。
输出格式
一行一个整数,表示最少分几个考场。
样例输入
5
8
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5
样例输出
4
样例输入
5
10
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
样例输出
5
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <algorithm>
#define PI 3.1415926535898
#define e 2.718281828459
using namespace std ;
const int MAX = 1005 ;
typedef long long LL ;
int n ,m ;
int ans ;
int g[MAX][MAX] ; // 表示是否存在关系
int vis[MAX][MAX] ; //
//vis[1][1] = 2 表示考场1里面第一个人是2号学生
// vis[1][2] = 3 表示考场1里面第二个认识3号学生
int cnt[MAX] ; // 表示考场中的学生人数 ,cnt[1] = 2 表示考场1 有2名
void add(int u ,int v){
g[u][v] = 1 ;
g[v][u] = 1 ;
}
void dfs(int id , int num ){
if(num >= ans ){ // 剪枝
return ;
}
if(id == n+1){
ans = min(ans,num) ;
return ;
}
for(int i = 1 ; i<=num ; i++) {// 看看前num 考场能不能放进去
int k = 0 ;
bool flag = false ;
k = cnt[i] ; // 取出第i考场的学生人数 ,然后进行枚举
for(int j = 1 ; j<=k ;j++){ // 枚举第 i 个考场的学生
if(g[id][vis[i][j]] == 1 ){ // 只要这个考场中有一个认识的也不行
flag = true ;
break;
}
}
if(!flag){ // 如果都不认识
vis[i][++cnt[i]] = id ; // 将这个学生加到这个教室中
dfs(id+1,num) ; // 安排下一个学生
cnt[i]--; //回溯
}
}
vis[num+1][++cnt[num+1]] =id ; // 没有的满足要求的教室,就重新开一个
dfs(id+1,num+1) ;
--cnt[num+1] ;
}
int main(){
cin >> n >> m ;
for(int i = 0 ;i<m ; i++ ){
int a ,b ;
cin >> a >>b ;
add(a,b) ;
}
ans = n ;
dfs(1,0) ;
cout<<ans;
return 0 ;
}