【图论】B057_LC_分考场(图着色+尽量避免新开考场)

n个人参加某项特殊考试。
为了公平,要求任何两个认识的人不能分在同一个考场。
求是少需要分几个考场才能满足条件。

输入
第一行,一个整数n(1 第二行,一个整数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
方法一:dfs

图的着色:问至少要多少种颜色,才能将图染完,且相邻结点的颜色不同

因为要最少考场,故每一个结点都要对检查历史中的考场看能否分配进去,能就尽量进去,不分配新考场…

能进入一个考场的条件是:考场中的人都不认识

#include
using namespace std;
const int N=105;
int n, m, ans=INT_MAX/2, mk[N][N], cnt[N];  //mk[i][j]记录第i个考场的第j个结点的颜色,cnt[i]记录i个考场的结点数
bool knew[N][N];

void dfs(int i, int s) {    //c当前分配结点数,s颜色种类数
    if (s>=ans) return;
    if (i>n) {
        if (s<ans) ans=s;
        return;
    }
    for (int j=1; j<=s; j++) { //之前分配的考场
        int noknew=0;
        for (int k=1; k<=cnt[j]; k++) if (!knew[i][mk[j][k]]) {
            noknew++;
        }
        if (noknew==cnt[j]) {
            cnt[j]++, mk[j][cnt[j]]=i;
            dfs(i+1, s);
            cnt[j]--;
        }
    }
    cnt[++s]++, mk[s][cnt[s]]=i;
    dfs(i+1, s);
    cnt[s]--;
}

int main() {
    std::ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for (int k=0; k<m; k++) {
        int u,v; cin>>u>>v;
        knew[u][v]=knew[v][u]=true;
    }
    dfs(1, 0);
    cout << ans;
    return 0;
}

你可能感兴趣的:(#,图论)