原创
问题描述
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
此题类似图着色问题:https://baike.baidu.com/item/%E5%9B%BE%E7%9D%80%E8%89%B2%E9%97%AE%E9%A2%98/8928655?fr=aladdin,
一个无向图着色,要求相邻的点不能是同色,方案有多种,找出所用颜色数最少的方案即可解题。
着色过程是按点顺序一一着色,n个点,一一按顺序为点1~n着色,着色完一个点继续着色下一个点,直至着色完n个点。
由于一个点可以多种合理的着色方案,不同的着色方案对最终的颜色种数影响是不同的,所以需要一一比较所有的方案,过程类似
深搜回溯。
1 import java.util.*; 2 3 public class Main { 4 5 static int n; //考试人数 6 static int m; //m个关系 7 static int matrix[][]; //邻接矩阵 8 static int max=0; //用了的颜色数 9 static int pid_Color[]; //存储点用了哪种颜色 10 static int flag=0; 11 static int res=99999; 12 13 static boolean judge(int pid,int color) { 14 for(int i=1;i<=n;i++) { 15 //邻接点判断 16 if(matrix[pid][i]==1) { 17 //判断邻接点是否涂色 18 if(pid_Color[i]!=0) { 19 //邻接点颜色判断 20 if(pid_Color[i]==color) { 21 return false; 22 } 23 } 24 } 25 } 26 return true; 27 } 28 29 static void color_Painting(int pid,int color_Num) { //pid代表点,目前已经用了color_Num种颜色 30 if(color_Num>=res) { 31 return; 32 } 33 if(pid>n) { 34 res=res<color_Num?res:color_Num; 35 return; 36 } 37 //枚举颜色1~color_Num,看看可不可以用在点pid 38 for(int color=1;color<=color_Num;color++) { 39 //可以 40 if( judge(pid,color)==true ) { 41 pid_Color[pid]=color; //涂色 42 color_Painting(pid+1,color_Num);//涂下一个点 43 pid_Color[pid]=0; 44 } 45 } 46 //颜色1~color_Num都用不了,用新的颜色 47 pid_Color[pid]=color_Num+1; 48 color_Painting(pid+1,color_Num+1); 49 pid_Color[pid]=0; 50 } 51 52 public static void main(String[] args) { 53 Scanner reader=new Scanner(System.in); 54 n=reader.nextInt(); 55 m=reader.nextInt(); 56 matrix=new int[n+1][n+1]; //编号从1开始 57 pid_Color=new int[n+1]; 58 //读入m个关系 59 for(int i=1;i<=m;i++) { 60 int a=reader.nextInt(); 61 int b=reader.nextInt(); 62 //无向图 63 matrix[a][b]=1; 64 matrix[b][a]=1; 65 } 66 color_Painting(1,0); 67 System.out.println(res); 68 } 69 }
代码2:
1 import java.util.*; 2 3 public class Main { 4 5 static int n; //学生人数 6 static int m; //关系 7 //邻接矩阵 8 static int matrix[][]; 9 //room[i][j]=z代表教室room[i]的第j个座位坐着同学z 10 static int room[][]; 11 //room_num[i]存储教室room[i]目前坐了多少位同学 12 static int room_num[]; 13 static int res=1000; 14 15 static void sit(int stu,int pos) { //stu表示第stu个学生,pos表示目前用了pos个教室 16 if(pos>=res) { 17 return; 18 } 19 if(stu>n) { 20 res=res<pos?res:pos; 21 return; 22 } 23 //判断前面1~pos个教室能不能放入同学stu 24 for(int i=1;i<=pos;i++) { 25 //对于教室room[i],只要同学stu不认识里面的其他所有同学即可放入,可以判断stu在此教室不认识的人数是否等于room_num[i] 26 int total=0; //统计stu在此教室room[i]不认识的人数 27 for(int j=1;j<=room_num[i];j++) { 28 if(matrix[stu][room[i][j]]==0) { 29 total++; 30 } 31 } 32 //stu不认识教室room[i]里面的所有人 33 if(total==room_num[i]) { 34 room[i][++room_num[i]]=stu; //放入stu 35 sit(stu+1,pos); //考虑下一位同学,因为没有开辟新的教室,所以还是只用了pos个教室 36 //回溯的原因:学生stu虽然可以放在教室room[a],但也许可以放入room[b],这两种放法对所需开辟的最小教室量是不同的,所以需要枚举所有情况 37 room_num[i]--; 38 } 39 } 40 //来到此步,说明教室1~pos都放不下学生stu,必须开辟新的教室 41 room[pos+1][1]=stu; //将stu放入新的教室 42 room_num[pos+1]++; 43 sit(stu+1,pos+1); 44 room_num[pos+1]--; //回溯 45 } 46 47 public static void main(String[] args) { 48 Scanner reader=new Scanner(System.in); 49 n=reader.nextInt(); 50 m=reader.nextInt(); 51 matrix=new int[n+1][n+1]; 52 room=new int[101][101]; 53 room_num=new int[101]; 54 //读入边 55 for(int i=1;i<=m;i++) { 56 int one=reader.nextInt(); 57 int two=reader.nextInt(); 58 matrix[one][two]=1; 59 matrix[two][one]=1; 60 } 61 sit(1,0); 62 System.out.println(res); 63 } 64 65 }
16:53:43
2018-08-11