0
点赞
收藏
分享

微信扫一扫

历届试题 分考场(dfs + 剪枝)

芝婵 2023-02-17 阅读 118


                                                      分考场      

问题描述

  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 ;
}

 

举报

相关推荐

0 条评论