题目
思路
遍历所有合法的染色情况,找出色数最小的
代码
#include <bits/stdc++.h>
#define MAXN 30
using namespace std;
int n, m;
int edge[MAXN][MAXN]={{0}}; // 边表
bool book[MAXN]={0}; // 点是否被染过色
// colorsCanUse[i][j]:点i是否能用颜色j
//bool colorsCanUse[MAXN][MAXN];
//int colorOfPoint[MAXN];
int colorNum=0; // 当前到哪个颜色
int finalColorNum=MAXN+1;
int finalColorOfPoint[MAXN];
typedef struct
{
int num; // 邻域中点的个数
int idx;
// vector<int> v; // 邻居
}nodeNeighbor;
nodeNeighbor neighbor[MAXN];
bool myCmp(nodeNeighbor a,nodeNeighbor b)
{
return a.num>b.num;
}
// 计算每个点的邻域,并按邻居个数降序排序
void calculateNeighbor()
{
for(int i=0;i<n;i++)
{
int cnt=0; // 求解每个点的相邻边数
for(int j=0;j<n;j++)
{
cnt+=edge[i][j];
}
neighbor[i].num=cnt;
neighbor[i].idx=i;
}
sort(neighbor,neighbor+n,myCmp);
}
// 获得mcv
int calculateMCV()
{
int i=0;
while(i<n&&book[neighbor[i].idx])
i++;
return neighbor[i].idx;
}
// 检查是否所有点都已被上色
bool isAllPointsColored()
{
for(int i=0;i<n;i++)
{
if(book[i]==false)
return false;
}
return true;
}
// 递归寻找染色情况
// 每得到一个合法的染色情况时,比较当前情况是否更优
void propagate(int node, int color, int colorOfPoint[MAXN], bool colorsCanUse[MAXN][MAXN])
{
// 注意相等情况也可直接跳过
if(color>=finalColorNum)
{
return;
}
// 获得一个合法染色,判断是否更优
if(isAllPointsColored())
{
// 获得当前色数
int* maxEle=max_element(colorOfPoint,colorOfPoint+n);
colorNum=*maxEle;
if(colorNum<finalColorNum)
{
finalColorNum=colorNum;
for(int i=0;i<n;i++)
finalColorOfPoint[i]=colorOfPoint[i];
}
return;
}
// 如果使用全局变量,每次递归结束返回时都无法恢复原数组
// 作为colorOfPoint的临时变量,用作传参
int tmp[MAXN]={0};
for(int i=0;i<n;i++)
tmp[i]=colorOfPoint[i];
// 作为colorsCanUse的临时变量,用作传参
bool tmp1[MAXN][MAXN];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
tmp1[i][j]=colorsCanUse[i][j];
}
// 处理邻域
// for(int i=0;i<neighbor[node].num;i++)
// {
// tmp1[neighbor[node].v[i]][color]=false;
// }
for(int i=0;i<n;i++)
{
if(edge[node][i])
tmp1[i][color]=false;
}
// 选定下一个染色的点
int mcv=calculateMCV();
// cout<<"mcv"<<mcv<<endl;
int currentColor=0;
for(;currentColor<n;currentColor++)
{
if(tmp1[mcv][currentColor]==true)
{
book[mcv]=true;
tmp[mcv]=currentColor;
propagate(mcv,currentColor,tmp,tmp1);
// 恢复book
book[mcv]=false;
// 不可省略,否则每次都会进入直接被返回的递归
if(currentColor>=finalColorNum)
return;
}
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
int u,v; cin>>u>>v;
edge[u][v]=edge[v][u]=1;
}
bool colorsCanUse[MAXN][MAXN];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
colorsCanUse[i][j]=true;
}
calculateNeighbor();
int mcv=calculateMCV();
// cout<<"mcv"<<mcv<<endl;
int colorOfPoint[MAXN];
for(int i=0;i<n;i++)
colorOfPoint[i]=-1;
colorOfPoint[mcv]=colorNum;
book[mcv]=true;
propagate(mcv,colorNum,colorOfPoint,colorsCanUse);
cout<<finalColorNum+1<<endl;
for(int i=0;i<n;i++)
cout<<finalColorOfPoint[i]<<endl;
return 0;
}