分析:把n个学生设为n个不同的结点,认识的学生用线连接。注意这题与图的着色问题的区分,图的着色问题要求点与点之间的连线不可交叉,而这题显然是可以的,所以这题不可用四色原理解决。又由于这题数据规模较小,所以这里我们可以直接用深搜解决。
思路:
初始化:假设n个学生的序号为1~n。以二维矩阵matrixs存储不同学生之间的联系,1表示有联系,0表示没有联系。以二维矩阵room表示m个考场容纳的学生。从学生1开始递归。
递归:
1.假设目前有一个考场,从学生1开始递归。若该次递归满足递归条件,则进行步骤二,否则,跳出该次递归。
2.把学生i安置到rnum个考场中的一个,并按考场序号从1开始依次判断每个考场中的学生是否与该学生有联系,若没有,则把该学生安置到该考场,然后对学生 i+1 进行递归。若没有考场符合条件,则把该学生安置到rnum+1考场,再对学生i+1进行递归。
#include <bits/stdc++.h>
#define maxn 234
using namespace std;
int matrixs[maxn][maxn] = {}, room[maxn][maxn] = {};
int num, cnt;
void dfs(int xx, int rnum)
{
///cout << xx << " " << rnum << endl;
if(rnum >= cnt) return;
///注意这里,是只要考场数比目前最小考场数小就可以剪枝了
if(xx == num + 1)
{
cnt = min(cnt, rnum);
///cout << cnt << "****" << endl;
return;
}
int jj, kk = 0;
///jj表示第几个考场,kk表示第jj个考场的第kk个座位
for(jj = 1; jj <= rnum; jj++)
{
kk = 0;
while(room[jj][kk] && !matrixs[xx][room[jj][kk]]) kk++;
if(room[jj][kk] == 0)
{
room[jj][kk] = xx;
dfs(xx + 1, rnum);
room[jj][kk] = 0;
}
}
room[rnum + 1][0] = xx;
dfs(xx + 1, rnum + 1);
room[rnum + 1][0] = 0;
}
int main()
{
int m;
scanf("%d %d", &num, &m);
{
memset(matrixs, 0, sizeof(matrixs));
memset(room, 0, sizeof(room));
cnt = num;
for(int i = 1; i <= m; i++)
{
int ss, tt;
scanf("%d %d", &ss, &tt);
matrixs[ss][tt] = matrixs[tt][ss] = 1;
}
dfs(1, 1);
printf("%d\n", cnt);
}
return 0;
}