问题描述
n个人参加某项特殊考试。
为了公平,要求任何两个认识的人不能分在同一个考场。
求是少需要分几个考场才能满足条件。
输入格式
第一行,一个整数n(1<n<100),表示参加考试的人数。
第二行,一个整数m,表示接下来有m行数据
以下m行每行的格式为:两个整数a,b,用空格分开 (1<=a,b<=n) 表示第a个人与第b个人认识。
输出格式
一行一个整数,表示最少分几个考场。
最近的思维定势特别多,需要改正。第一眼看这题,woc这肯定是最大团了。毕竟一个子完全图的各个端点肯定属于不同的考场。迅速地写了一发交上去WA。后来想了一段时间才意识到根本和最大团没啥关系,答案的数目完全可以比最大团的大小要大。一个例子就是五个端点的环,最大团是2,然而必须要三个教室,类似的图还有:
这个图最大团是3,但是拿三色去染会发生矛盾,至少需要四色。
实际上这题的解法,还是需要暴搜,从左到右枚举每个编号的同学,枚举他能呆在哪个已有的教室,或是呆在一个新教室。乍一看100好像很大,实际上写得正常的话都可以过,数据不那么恶心。
#include<cstdio>
#include<vector>
#include<algorithm>
#include<bitset>
using namespace std;
int n,m,cnt,ans=1E9,h[105];
vector<int> E[105];
bitset<105> B[105];
bool get(int x) //提取可能选择
{
for(int j=0;j<E[x].size();j++)
if(h[E[x][j]])
B[x][h[E[x][j]]]=true;
}
void dfs(int x)
{
if(cnt>=ans)
return ;
if(x>n)
{
ans=cnt;
return ;
}
B[x].reset();
get(x);
for(int i=1;i<=cnt;i++)
if(!B[x][i])
{
h[x]=i;
dfs(x+1);
h[x]=0;
}
cnt++;
h[x]=cnt;
dfs(x+1); //新教室
h[x]=0;
cnt--;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++)
{
scanf("%d%d",&u,&v);
if(u>v)
swap(u,v);
E[v].push_back(u);
}
for(int i=1;i<=n;i++)
sort(E[i].begin(),E[i].end()),unique(E[i].begin(),E[i].end());
dfs(1);
printf("%d",ans);
return 0;
}