问题描述
n个人参加某项特殊考试。
为了公平,要求任何两个认识的人不能分在同一个考场。
求是少需要分几个考场才能满足条件。
为了公平,要求任何两个认识的人不能分在同一个考场。
求是少需要分几个考场才能满足条件。
输入格式
第一行,一个整数n
(1<n<100),表示参加考试的人数。
第二行,一个整数m,表示接下来有m行数据
以下m行每行的格式为:两个整数a,b,用空格分开 (1<=a,b<=n) 表示第a个人与第b个人认识。
(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
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
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<vector> using namespace std; #define MAXN 110 #define INF 0x3f3f3f3f; int graph[MAXN][MAXN];//建立图 int cun[MAXN][MAXN];//存储第几个教师有谁谁谁 int cnt[MAXN]={0};//记录每个教室的人数 int res=INF;//假设需要一个无穷多的教室 int n,m;//定义人数,以及认识的数目 void solve(int id,int num)//回溯搜索,id表示当前安排的是第id的同学,num表示当前安排这个id同学的时时候已经用了多少个教室 { if(num>=res)//如果当前的教室方案已经超过以前的方案了,那么就放弃返回 return; if(id>n)//如果说id的同学的id>n说明全部的同学都安排完了 { res=num;//如果执行到这一步说明res一定是.>num的,所以更新一下 return;//返回 } for(int i=0;i<num;i++)//扫描每一个已经存在的教室 { int len=cnt[i];//取一下当前i教室的人数 int c=0;//这个变量表示当前id的同学和这个教室的同学不认识的人数 for(int j=0;j<len;j++)//扫描这个教室的每一个同学 { if(graph[id][cun[i][j]]==0)//如果没有关系 c++;//加1 } if(c==len)//如果全部不认识 { cun[i][cnt[i]++]=id;//那么id同学就进入这个教室,同时这个教室的人数+1 solve(id+1,num);//那么安排下一个教室 cnt[i]--;//递归返回之后把这个同学在从这个教室分走,分到下几个教室看看 } } cun[num][cnt[num]++]=id;//如果全部教室都存在id认识的同学,那么就把这个同学新开个教室 solve(id+1,num+1);//递归下一个同学并且当前的教室数目+! cnt[num]--;//返回后移除这个同学看下上一个同学有没有其他的选择 } int main() { cin>>n>>m; for(int i=0;i<m;i++) { int a,b; cin>>a>>b; graph[a][b]=1; graph[b][a]=1;//如果两个人认识的话就可以标记成1,c++在数组创建 的时候已经快速初始化 } solve(1,0);//进入回溯更新最小的教室数目 cout<<res;//输入所有可能中的最小的答案 }