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; }