蓝桥杯 历届试题 分考场 图的染色问题

开始看到这道题,还以为是并查集的变异题(因为写这题之前恰好写的并查集题,后来到网上看了下题解,发现并不是自己想的

此题是一道经典的图的染色问题,等同于:对图经行染色,且相邻的顶点不能染同样的颜色,问至少需要多少种不同的颜色

 

问题描述

  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
 

AC代码

程序代码的注释讲解应该够看了
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = (int)1e3 + 10;
const int INF = (int)2e9 + 10;
int G[MAXN][MAXN];//G[i][j]=1表示i和j认识,否则不认识
int stu[MAXN][MAXN];//stu[i][j]=x 表示第i个房间第j个人是编号为x的学生
int room[MAXN];//room[i]=k  表示第i个房间有k个人
int res = INF;//假设一开始需要无穷多个房间
int n,m,a,b;

void dfs(int x,int total){  //x表示当前学生的编号,total表示用掉房间的数量
    if (total >= res)  //如果当前用掉房间的数量大于历史用掉的最小数量,返回
        return;
    if (x == n + 1){    //如果学生已经安排完了,取最优值,并返回 
        res = min(total, res);
        return;
    }
    for (int i = 1; i <= total; i++){  //遍历所有房间
        int k = 0;  //计数器
        int len = room[i];  //第i个房间的有多少人
        for (int j = 1; j <= len; j++){  //遍历当前房间的所有学生
            if (!G[x][stu[i][j]])  //如果学生x与学生stu[i][j]没有关联,k++;
                k++;
        }
        if (k == len){  //如果x与当前房间所有的人都没有关联
            stu[i][++room[i]] = x;  //那么就把x放进这个房间里
            dfs(x + 1, total);  //当前学生已经被安排,dfs安排下一个学生
            room[i]--;  //回溯
        }
    }
    //如果所有房间都与x有关,则要另开一间新的房间安排给x
    stu[total+1][++room[total+1]] = x;
    dfs(x + 1, total+1);  //安排下一个学生
    room[total+1]--;//回溯

}
int main()
{
    ios::sync_with_stdio(false);  //加快cin的输入
    cin >> n>>m;
    memset(G,0,sizeof(G));
    memset(stu, 0, sizeof(stu));
    memset(room, 0, sizeof(room));
    for (int i = 1; i <= m; i++){
        cin >> a >> b;
        G[a][b] = G[b][a] = 1;
    }
    dfs(1, 0);
    cout << res << endl;
    return 0;
}
View Code

题解效率

 

 

转载于:https://www.cnblogs.com/looeyWei/p/10439834.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值