#################本文为学习《图论算法及其MATLAB实现》的学习笔记#################
- 均匀全染色以及均匀全色数
若图G的一个全染色满足使任意两种颜色所染元素数目相差不超过1,则称其为图G的均匀全染色,其所用最少色数称为图G的均匀全色数。
- 算法用途
给出简单图的尽可能少的均匀全染色数方案
- 算法思想
先对图进行全染色,找到一个数量最少的染色,然后对图进行重新染色,使得重新的染色满足均匀染色的要求。
- 程序参数说明
M: 任意图的邻接矩阵
k: 染色数
C: 顶点染色方案
W: 边集合的染色方案,以矩阵形式输出
nk: 统计各种颜色所用的次数
- 算法的matlab程序详解
ps.程序中提到的全染色程序可见《全染色算法及其matlab程序详解》
算法核心为在重新全染色的每次染色前判断是否满足均匀染色
function [k,C,W,nk] = graphunicodf(M)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%% 均匀全染色算法 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%% 输入: M: 任意图的邻接矩阵;
%%%%%%%%% 输出: k: 染色数
%%%%%%%%% C: 顶点染色方案
%%%%%%%%% W: 边集合的染色方案,以矩阵形式输出
%%%%%%%%% nk: 统计各种颜色所用的次数
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[k,C,W] = graphcodf(M); % 得到图的全染色方案
%%%%%%%%%%%%%%%%% 找到一个数量最少的染色 %%%%%%%%%%%%%%%%
C1 = [C' W]; % 将 C 转置与 W 组合成新的矩阵
mk = max(max(C1)); % 得到 C1 中最大元素值,即最大染色号
sm = mk;
for i = 1:mk
a = sum(sum((C1 == i))); % 统计 C1 中色号为 i 的元素数量
if a > 0
sm = min([sm a]);
end
end
sm; % sm 为色号最小染色数
G = M;
n = size(G,1); % 得出 G 的行数
%%%%%%%%%%%%%%%%%%% 对图进行重新染色 %%%%%%%%%%%%%%%%%%%%%%
W = G;
for i = 1:n
for j = 1:(i-1)
W(i,j) = 0; % 使 W 主对角线下三角区元素全为零
end
end
C = zeros(1,n); % C 为1行n列的全零数组
i = 1;
k = 1; % 初始待染色号为 1 色
Z = [1:n]; % 建立一个1到n的数组
while sum(find(C == 0))
%%%%%%%% 对没有染色的顶点染色 %%%%%%%%
if C(1,i) == 0 % 如果第 i 个顶点未被染色
C(1,i) = k; % 将第 i 个顶点染为 k 色
num = 1;
if num - sm > 1 % 当前色号染色数与最小染色数相差大于1,不满足均匀全染色
k = k+1; % 更新色号
end
Sn = find(G(i,:) ~= 0); % Sn 为 G 中第i行非零元素的索引值,即找到与当前选中点相邻的顶点
flag = 1;
while flag
tc = setdiff(Z,Sn); % tc 为在 Z 中而不在 Sn 中的元素,即找到与当前选中点不相邻的顶点
if isempty(tc)
flag = 0;
else
c = G(tc(1),:); % c 为 G 的第 tc(1) 行
c(1,tc(1)) = 1; % 使 c 的 (1,tc(1)) 元素为1
num = num+1;
if num - sm > 1
k = k+1;
end
C(tc(1)) = k; % 使数组 C 中的第 tc(1) 个元素为k,即将与选中点不相邻的顶点染成 k 色
Sn1 = find(c ~= 0); % Sn1 为 c 中元素不为0的索引值
Sn = union(Sn,Sn1); % Sn(新) 为 Sn 与 Sn1 的并集
end
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%% 对相应的边集合进行染色 %%%%%%%%
for j = (i+1):n
W1 = W;
if W(i,j) == 1 % 寻找与顶点 i 相关联的边
k = k+1; % 更新待染色号 k
W(i,j) = k; % 对与顶点 i 相关联的边(i,j)染色
num = 1;
if num - sm > 1
k = k+1;
end
W1(:,i) = 0;W1(:,j) = 0; % 将 W1 的第i列和第j列元素变为0
W1(i,:) = 0;W1(j,:) = 0; % 将 W1 的第i行和第j行元素变为0
m = 0;
while sum(sum(W1)) ~= 0 & m == 0
c2 = find(W1 ~= 0); % c2 为 W1 中非零元素索引值
c3 = find(W == 1); % c3 为 W 中元素值为1的索引值
c4 = intersect(c2,c3); % c4 为 c2 与 c3 中相同的元素,即找到与已染色边 (i,j) 不相邻的边
if ~isempty(c4) % 若 c4 非空,即找到与已染色边 (i,j) 不相邻的边
k1 = floor(c4(1) / n); % 对 c4(1)/n 取余
k2 = mod(c4(1),n); % 对 c4(1)/n 取模,即找到与新边相关联的顶点
if k2 == 0
k2 = n;
end
W1(k2,:) = 0;W1(:,k2) = 0; % 将 W1 的第k2行和第k2行元素变为0
W1((k1+1),:) = 0;W1(:,(k1+1)) = 0; % 将 W1 的第k1+1行和第k1+1行元素变为0
num = num+1;
if num - sm > 1
k = k+1;
end
if k1+1 < k2
W((k1+1),k2) = k;
else
W(k2,(k1+1)) = k; % 对新边进行染色
end
else
m = 1;
end
end
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
i = i+1;
k = k+1;
end
%%%%%%%%%%%%%%%% 计算总染色数 %%%%%%%%%%%%%%%%%%%
k = k-1;
m = 0;
for i = 1:k
t1 = find(C == i); % 找到染色为 i 的顶点索引值集合
t2 = find(W == i); % 找到染色为 i 的边索引值集合
t3 = sum(t1);
t4 = sum(sum(t2));
t5 = t3 + t4;
if t5 ~= 0
m = m+1; % 总染色数+1
end
end
k = m;
%%%%%%%%%%%%%%% 统计各种颜色所用的次数 %%%%%%%%%%%%%%%
C1 = [C' W]; % C1 为均匀全染色后顶点集与边集组成的增广矩阵
mk = max(max(C1)); % mk 为最大色号
nk = zeros(2,k);
l = 1;
for i = 1:mk
a = sum(sum((C1 == i))); % a 为 C1 中色号为 i 元素的个数
if a > 0
nk(:,l) = [i a];
l = l+1;
end
end
nk;