链接:历届试题 - 分考场
问题描述
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
分析:
因为n<100,所以用DFS暴力即可,不过要剪枝
对于一个人,要么 放入已有的考场(前提是该考场没有其认识的人),要么 放入一个新考场。以这样的思路的DFS就行。
可以用vector来操作,虽然方便,不过遍历速度会慢些。
以下代码:
#include<cstdio>
#include<vector>
#include<algorithm>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=110;
int n,m,ans=INF;
bool G[maxn][maxn]={false}; //G[a][b]为1表示a,b认识,为0表示a,b不认识
vector<int> room[maxn]; //表示考场
void DFS(int i,int j) //i表示当前处理的人的编号,j表示考场数
{
if(j>=ans) //剪枝
return;
if(i>n) //i>n说明已处理完所有人
{
ans=min(ans,j);
return;
}
//放入已有考场
for(int k=1;k<=j;k++)
{
bool ok=true;
for(int l=0;l<room[k].size();l++)
{
if(G[room[k][l]][i])
{
ok=false;
break;
}
}
if(ok)
{
room[k].push_back(i);
DFS(i+1,j);
room[k].pop_back(); //别忘了这个
}
}
//放入新考场
room[j+1].push_back(i);
DFS(i+1,j+1);
room[j+1].pop_back(); //也别忘了这个
}
int main()
{
scanf("%d %d",&n,&m);
int a,b;
while(m--)
{
scanf("%d %d",&a,&b);
G[a][b]=true;
G[b][a]=true;
}
DFS(1,0);
printf("%d",ans);
return 0;
}