[原理讲解及实例讲解参见我上传的资源PPT](https://download.csdn.net/download/jane0819/87232208)
在基础上增加了三种边权值的仿真:
function match = KM(r)
global g_map;
global g_m;
global g_n;
global g_label_value_x;
global g_label_value_y;
global g_match_x;
global g_match_y;
global g_min_weight_diff;
global g_visible_x;
global g_visible_y;
global times;
%% 模拟边权值
rng('default');
% r = round(rand(10,15)*50) % 初始化边权值
% r(r>15) = 0 % 创造稀疏矩阵
r = (rand(10,15)*1) % 模拟0~1概率矩阵
r = round(r*30); % 放大截断0~1概率矩阵
%% 保存图像到视频
bSaveAVI = 0;
if bSaveAVI
aviname = input('input the file name for avi: ','s');
AVIOBJ = VideoWriter(aviname);
AVIOBJ.Quality = 60;
AVIOBJ.FrameRate = 16;
open(AVIOBJ);
end
%% 是否画图
bPlotMatch = 0;
%% 初始化左侧顶标值 = g_map每行最大值
[g_m,g_n] = size(r);
g_map = r; % 二分图的权值
g_label_value_x = zeros(g_m,1);
g_label_value_y = zeros(g_n,1);
g_match_x = ones(g_m,1)*-1;
g_match_y = ones(g_n,1)*-1;
for i = 1:g_m
for j = 1:g_n
if g_label_value_x(i) < g_map(i,j)
g_label_value_x(i) = g_map(i,j);
end
end
end
%% KM-algorithm
times = 0; % 记录时间复杂度
for i = 1:g_m
times = times + 1;
while(1)
g_min_weight_diff = 10^10;
g_visible_x = zeros(g_m,1);
g_visible_y = zeros(g_n,1);
if dfs(i) || g_min_weight_diff == 10^10 || g_label_value_x(i) == 0
% 要么找到匹配项dfs(i)==true;
% 要么无任何可匹配项,g_min_weight_diff == 10^10无相等子图;
% 要么初始匹配即==0
break;
end
% 被访问过的顶标值进行修改
for j = 1:g_m
if g_visible_x(j)
g_label_value_x(j) = g_label_value_x(j) - g_min_weight_diff;
end
end
for j = 1:g_n
if g_visible_y(j)
g_label_value_y(j) = g_label_value_y(j) + g_min_weight_diff;
end
end
end
if bPlotMatch
plotMatch(r,g_match_x);
if bSaveAVI
frame = getframe(gca); %把图像存入视频文件中
im = frame2im(frame);
writeVideo(AVIOBJ,im);
pause(3);
end
end
end
match = g_match_x;
if bPlotMatch
plotMatch(r,match);
if bSaveAVI
close(AVIOBJ); %%关闭视频文件句柄
end
end
disp(['n^3 = ',num2str((min([g_m;g_n]))^3),', 时间复杂度 = ',num2str(times)]);
function res = dfs(i)
%% 深度优先搜索
global g_map;
global g_m;
global g_n;
global g_label_value_x;
global g_label_value_y;
global g_match_x;
global g_match_y;
global g_min_weight_diff;
global g_visible_x;
global g_visible_y;
global times;
g_visible_x(i) = 1;
for j = 1:g_n
times = times + 1;
if(~g_visible_y(j) && g_map(i,j) > 0)
tmp = g_label_value_x(i) + g_label_value_y(j) - g_map(i,j);
if tmp < 10^-5
% 顶标和=边权值,即tmp==0
g_visible_y(j) = 1;
if(g_match_y(j) == -1 || dfs(g_match_y(j)))
g_match_x(i) = j;
g_match_y(j) = i;
res = true;
return
end
elseif tmp > 0
% 顶标和<边权值
if tmp < g_min_weight_diff
g_min_weight_diff = tmp; % 边权和顶标最小的差值
end
end
end
end
res = false;
function plotMatch(r,match)
global g_label_value_x;
global g_label_value_y;
figure(1)
clf
[g_m,g_n] = size(r);
for i = 1:g_m
A(i,1) = 5;
A(i,2) = 5*i;
hold on
plot(A(i,1),A(i,2),'k.', 'MarkerFaceColor','k', 'MarkerSize',30)
text(A(i,1)-5,A(i,2),['A' num2str(i) '=' num2str(g_label_value_x(i))]);
end
for i = 1:g_n
B(i,1) = 25;
B(i,2) = 5*i;
hold on
plot(B(i,1),B(i,2),'k.', 'MarkerFaceColor','k', 'MarkerSize',30)
text(B(i,1)+3,B(i,2),['B' num2str(i) '=' num2str(g_label_value_y(i))]);
end
xlim([-10,40]);ylim([0,5*g_n+5]);
for i = 1:g_m
for j = 1:g_n
hold on;
plot([A(i,1),B(j,1)],[A(i,2),B(j,2)],'y-','LineWidth',2);
text(A(i,1)+0.7*(-A(i,1)+B(j,1)),A(i,2)+0.7*(-A(i,2)+B(j,2)),num2str(r(i,j)));
end
hold on
if match(i) > 0
plot([A(i,1),B(match(i),1)],[A(i,2),B(match(i),2)],'b-','LineWidth',4);
end
end
pause(0.6);
end