一.着色问题
1.问题描述
存在一个无向图,要求给图中的点涂色,并且有线连接的点之间不能是同一种颜色。
2.输入格式
第一行为两个正整数 n , m ( 0 < n , m < 100 ) 分别表示录入的图的点数以及边数
第二行为一个正整数num,表示能用的颜色数(每种颜色用一个正整数来表示,从 1 开始逐渐增 1 的正整数)
之后为m行,每行两个数x,y,表示点x和y之间有一条边(点从 1 开始,为逐渐增 1 的正整数)
3.输出格式
输出在当前情形下的上色方案的数量
4.问题分析
4.1 判断位置为pos的点是否能够涂上代号为x的颜色
4.2 dfs搜索
对图进行遍历,可以使用深度优先搜索。对于上色方案,我们首先考虑点1上什么颜色(遍历所有的颜色),再考虑点2,……。由于前面点的限制,后面的点的上色会受限。
此时每形成一种方案就需要进行回退。
5.代码实现
//着色问题
#include <iostream>
using namespace std;
const int N=110;
bool map[N][N]={false};
int color[N]={0};//color[i]=x 表示第i个点涂上代号为x的颜色
int n,m,num,ans=0;
bool judge(int pos,int x){
for(int i=1;i<=n;i++)
if(map[pos][i]&&color[i]==x)
return false;
return true;
}
void dfs(int pos){
if(pos>n){
ans++;
return;
}
for(int i=1;i<=num;i++){
if(judge(pos, i)){
color[pos]=i;
dfs(pos+1);
color[pos]=0;
}
}
}
int main(int argc, const char * argv[]) {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int x,y;
cin>>n>>m>>num;
for(int i=0;i<m;i++){
cin>>x>>y;
map[x][y]=map[y][x]=true;
}
dfs(1);
cout<<ans<<'\n';
return 0;
}
二.分考场
1.问题描述
n个人参加某项特殊考试。
为了公平,要求任何两个认识的人不能分在同一个考场。
求至少需要分几个考场才能满足条件。
2.输入描述
第一行,一个整数n(),表示参加考试的人数。
第二行,一个整数m,表示接下来有m行数据
以下m行每行的格式为:两个整数a,b,用空格分开 () 表示第a个人与第b个人认识。
3.输出描述
输出一行一个整数,表示最少分几个考场。
4.问题分析
dfs的参数问题,每次需要知道安排的是第几个学生,当前已经开辟了多少个考场。
剪枝,如果当前开辟考场的数目已经大于了ans,那么直接return。
已经安排好所有的学生,则ans=roomNum。
遍历所有的教室,对每一个教室里的学生再进行遍历,判断当前正在安排的学生是否和教室里已有的学生认识。
若没有人认识当前学生,则将该学生放进该教室,并继续安排下一个学生,回退时需要将该学生从教室里清除。
若当前教室都不可用,则新开辟一件教室给该学生,并继续安排下一个学生,回退时需要将该学生从教室里清除。
5.代码实现
//分考场
#include <iostream>
#include <vector>
using namespace std;
const int N=110;
bool map[N][N]={false};
int n,m,ans=N;//ans需要赋一个初始值
vector <int> classroom[N];
void dfs(int num,int roomNum){
if(roomNum>=ans)//剪枝
return;
if(num>n){//已经安排好所有的学生
ans=roomNum;
return;
}
for(int i=1;i<=roomNum;i++){//遍历所有教室
int j=0,len=(int)classroom[i].size();
for(j=0;j<len;j++){//检测当前教室中是否有人与当前被安排的学生认识
if(map[num][classroom[i][j]])
break;
}
if(j==len){//没有学生与当前被安排的学生认识,当前被安排的学生可以被放进该教室
classroom[i].push_back(num);//当前教室插入该学生
dfs(num+1,roomNum);//继续安排下一个学生
classroom[i].pop_back();//回退时将当前学生从该教室清除
}
}
classroom[roomNum+1].push_back(num);//开一间新教室给当前学生
dfs(num+1,roomNum+1);//继续安排下一个学生
classroom[roomNum+1].pop_back();//回退时将当前学生从该教室清除
}
int main(int argc, const char * argv[]) {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int a,b;
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>a>>b;
map[a][b]=map[b][a]=true;
}
dfs(1,0);
cout<<ans<<'\n';
return 0;
}