开始看到这道题,还以为是并查集的变异题(因为写这题之前恰好写的并查集题,后来到网上看了下题解,发现并不是自己想的
此题是一道经典的图的染色问题,等同于:对图经行染色,且相邻的顶点不能染同样的颜色,问至少需要多少种不同的颜色
问题描述
n个人参加某项特殊考试。
为了公平,要求任何两个认识的人不能分在同一个考场。
求是少需要分几个考场才能满足条件。
为了公平,要求任何两个认识的人不能分在同一个考场。
求是少需要分几个考场才能满足条件。
输入格式
第一行,一个整数n(1<n<100),表示参加考试的人数。
第二行,一个整数m,表示接下来有m行数据
以下m行每行的格式为:两个整数a,b,用空格分开 (1<=a,b<=n) 表示第a个人与第b个人认识。
第二行,一个整数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
AC代码
程序代码的注释讲解应该够看了
View Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#include<iostream> #include<cstring> #include<algorithm> using namespace std; const int MAXN = (int)1e3 + 10; const int INF = (int)2e9 + 10; int G[MAXN][MAXN];//G[i][j]=1表示i和j认识,否则不认识 int stu[MAXN][MAXN];//stu[i][j]=x 表示第i个房间第j个人是编号为x的学生 int room[MAXN];//room[i]=k 表示第i个房间有k个人 int res = INF;//假设一开始需要无穷多个房间 int n,m,a,b; void dfs(int x,int total){ //x表示当前学生的编号,total表示用掉房间的数量 if (total >= res) //如果当前用掉房间的数量大于历史用掉的最小数量,返回 return; if (x == n + 1){ //如果学生已经安排完了,取最优值,并返回 res = min(total, res); return; } for (int i = 1; i <= total; i++){ //遍历所有房间 int k = 0; //计数器 int len = room[i]; //第i个房间的有多少人 for (int j = 1; j <= len; j++){ //遍历当前房间的所有学生 if (!G[x][stu[i][j]]) //如果学生x与学生stu[i][j]没有关联,k++; k++; } if (k == len){ //如果x与当前房间所有的人都没有关联 stu[i][++room[i]] = x; //那么就把x放进这个房间里 dfs(x + 1, total); //当前学生已经被安排,dfs安排下一个学生 room[i]--; //回溯 } } //如果所有房间都与x有关,则要另开一间新的房间安排给x stu[total+1][++room[total+1]] = x; dfs(x + 1, total+1); //安排下一个学生 room[total+1]--;//回溯 } int main() { ios::sync_with_stdio(false); //加快cin的输入 cin >> n>>m; memset(G,0,sizeof(G)); memset(stu, 0, sizeof(stu)); memset(room, 0, sizeof(room)); for (int i = 1; i <= m; i++){ cin >> a >> b; G[a][b] = G[b][a] = 1; } dfs(1, 0); cout << res << endl; return 0; }
题解效率