问题描述
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
样例输入
5
10
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
样例输出
5
解题思路
基本思路同图着色问题(回溯法)
但由于测试用例大,传统方法会造成运行超时
参考
https://blog.csdn.net/a447332241/article/details/87819537
答案
方法一:
基本思路同图着色问题(回溯法)
测试用例可以,但是提交测试用例大,会超时
参考
https://blog.csdn.net/a447332241/article/details/87819537
import java.util.Scanner;
public class Main {
static int[][] c=new int[100][100];
static int[] color=new int[100];
static int mincolor=100;
static int n;
static boolean ok(int k)
{
for(int i=1;i<k;i++)
{
//System.out.println(k+" "+i+" "+color[i]+" "+color[k]);
if(c[k][i]==1&&color[i]==color[k])
return false;
}
//System.out.println("ok:"+k+" "+color[k]);
return true;
}
//配色方案中有几种不同的颜色
static void check()
{
int num=0;
int j=1;
//判断第n个区域填的颜色,在之前n-1个区域中是否出现过
for(int i=1;i<=n;i++)
{
boolean flag=false;
for(j=1;j<i;j++)
if(color[i]==color[j]) {
flag=true;
break;
}
if(flag)
continue;
else {
++num;
}
}
if(num<mincolor) {
// for(int h=1;h<=n;h++){
// System.out.print(color[h]+" ");
// }
mincolor=num;
// System.out.println("mincolor="+mincolor);
}
}
static void group(int step)
{
if(step==n+1) {
check();
//System.out.println("发现一个可行解");
return;
}
else {
for(int i=1;i<=n&&i<mincolor;i++) {
color[step]=i;
if(ok(step)) {
//++step;
//System.out.println("结点"+step+" 颜色为"+color[step]);
group(step+1);
}
color[step]=0;//回溯置0 好像不写也没问题
}
}
return; //void默认返回,不用写return
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
n=sc.nextInt();//n-区域块数
int m=sc.nextInt();//m-m条边
for(int i=0;i<m;i++)
{
int x=sc.nextInt();
int y=sc.nextInt();
c[x][y]=c[y][x]=1;
//System.out.println(x+" "+y);
}
for(int i=1;i<=n;i++)
{
color[i]=0;
}
//System.out.println("输入完成");
group(1);
System.out.println(mincolor);
}
}
方法二:
参考:
https://blog.csdn.net/txb_txb/article/details/80346964