PREV-53 分考场

将该问题转化为无向图染色问题,相邻的顶点不然染相同的颜色是,然后用dfs,注意相应的数据结构和剪枝。

#include <bits/stdc++.h>
//无向图染色问题,相邻两个顶点不能染相同的颜色 
using namespace std;
#define MAXN 105

int G[MAXN][MAXN];//连接矩阵表示的图 
int room[MAXN][MAXN];//表示第几个房间里的第几个人是谁 
int cnt[MAXN];//表示每个房间人数 
int n,m,ans;

void dfs(int cur,int tol){//cur表示当前排的考生,tol表示当前已经占用的考场 
    int count;
    //没有该剪枝的话,时间复杂度会超标 
    if(tol >= ans) return;//如果个数超过但前最好解,则进行剪枝,用来降低实际按复杂度 
    if(cur > n) {//已经排完,将该种情况与之前的情况对比,取最优 
        ans = min(ans, tol);
        return;
    } 
 
    for(int i = 0; i < tol; i++) {//遍历每一个考场 
        int f = 1;
        for(int j = 0; j < cnt[i]; j++) {//检查当前考场的人是否与cur都不认识 
            int t = room[i][j];//考场中的每个人 
            if(G[cur][t]) {//如果认识的话就退出 
                f = 0;
                break;
            }
        }
        if(f) {//如果都不认识的话说明可以加入考场 
            room[i][cnt[i]++] = cur;//在当前考场计入x 
            dfs(cur+1, tol);//继续排下一个 
            --cnt[i];//回溯,将之前加入的去掉 
        }
    }
 
    room[tol][cnt[tol]++] = cur;//如果遍历所有考场,都不满足cur进入的条件,就新增加一个考场 
    dfs(cur+1, tol+1);//继续排下一个 
    --cnt[tol];//回溯 
}
int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n;//参加考试的人数 
    cin>>m;//m行数据 
    int a,b;
    for(int i=0;i<m;i++){
        cin>>a>>b;
        G[a][b] = G[b][a] = 1;
    }
    ans = 200;//取一个大数(表示最少房间个数)
    dfs(1,0); 
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2021-03-07 11:19  zmachine  阅读(52)  评论(0编辑  收藏  举报