均匀全染色算法及其matlab程序详解

#################本文为学习《图论算法及其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;

你可能感兴趣的:(图论,算法,图论,matlab)