[蓝桥杯]分考场

[蓝桥杯]分考场

分考场:
  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

解题思路:咋一看,这是一个分类问题,用并查集很简单。但其实并不是并查集的问题,而是图染色问题。图相邻顶点不能是相同颜色。这道题可以把两个认识的人看作图中有路径的两点,然后用dfs遍历点,遍历考室,如果该考室有该点认识的人,则检查下一个考室,反之加入该考室,并回溯。如果所有考室都有人认识该考生,那么就新增一个考室,然后回溯。直到所有学生都检查完了,再比较结果。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 101;

int n, m;

int G[maxn][maxn];
int room[maxn][maxn];

int num = maxn;

void dfs(int x, int r){
	if(r >= num) return ;
	
	if(x == n+1){
		num = min(num, r);
		return ;
	}
	
	int k, i;
	for(i = 1; i<=r; i++){
		k = 0;
		while(!G[room[i][k]][x] && room[i][k]) k++;
		if(room[i][k] == 0){ 
			room[i][k] = x;
			dfs(x+1, r);
			room[i][k] = 0;
		}
	}
	
	room[i][0] = x;
	dfs(x+1, r+1);
	room[i][0] = 0;
	
}

int main(){
	cin>>n>>m;
	
	memset(G, 0, sizeof(G));
	memset(room, 0, sizeof(room));
	for(int i = 0; i<m; i++){
		int a, b;
		
		cin>>a>>b;
		
		G[a][b] = G[b][a] = 1;
	}
	
	dfs(1, 1);
	
	cout<<num<<endl;
		
	return 0;
}
发布了63 篇原创文章 · 获赞 8 · 访问量 7189

猜你喜欢

转载自blog.csdn.net/s1547156325/article/details/104621900