问题描述
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
这里采用回溯+简单剪枝,解决思路类似将一个个人根据不同选择装在符合条件的不同的桶中,对这些选择进行扩枝再深搜,
而桶类似教室或考场。回溯是搜索到足够多的结果取其最优解。
import java.io.BufferedInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class Main {
private static final int MAXN=110;
private static boolean[][] map=new boolean[MAXN][MAXN];
private static int n,ans;
private static List<List<Integer>>list=new ArrayList<List<Integer>>();
private static boolean check(int index,int now){
for(int i=0;i<list.get(index).size();++i)
if(map[now][list.get(index).get(i)])
return false;
return true;
}
private static void backtrace(int now){
if(now==n+1){
ans=Math.min(ans,list.size());
return;
}
if(list.size()>=ans)
return;
for(int i=0;i<list.size();++i){
if(check(i,now)){
list.get(i).add(now);
backtrace(now+1);
list.get(i).remove(list.get(i).size()-1);
}
}
List<Integer>dataList=new ArrayList<Integer>();
dataList.add(now);
list.add(dataList);
backtrace(now+1);
list.remove(list.size()-1);
}
public static void main(String[] args) {
Scanner in=new Scanner(new BufferedInputStream(System.in));
while(in.hasNext()){
n=in.nextInt();
for(int i=1;i<=n;++i)
Arrays.fill(map[i], false);
list.clear();
int k=in.nextInt();
while(k--!=0){
int a,b;
a=in.nextInt();
b=in.nextInt();
map[a][b]=map[b][a]=true;
}
ans=1000000000;
backtrace(1);
System.out.println(ans);
}
in.close();
}
}