function [d, spath] = BellmanFord(arg1, arg2)
if isa(arg1,'graph') || isa(arg1,'digraph')
G = arg1;
if ismultigraph(G)
edges = table2array(G.Edges);
ij = edges(:,1:2);
w = edges(:,3);
n = max(ij,[],'all');
A = accumarray(ij, w, [n,n], @min, 0, true);
if isa(arg1,'graph')
A = triu(A,1).'+A;
end
else
A = G.adjacency('weight');
end
else
A = arg1;
end
if nargin < 2
start = 1;
else
start = arg2;
end
A = A.';
n = size(A,1);
start = max(min(start,n),1);
d = inf(n,1);
du = 0;
i = start;
if nargout < 2
while true
d(i) = du;
[i, j, dij] = find(A(:,i));
if isempty(i)
break
end
[du, p] = sort(du(j)+dij);
[i, p] = sort(i(p));
b = [true; diff(i,1,1)>0];
i = i(b);
du = du(p(b));
b = du < d(i);
i = i(b);
du = du(b);
end
else
prev = cell(n,1);
neig = inf(1,n);
for c = 0:n-1
d(i) = du;
neig(i) = c;
jprev = i;
[i, j, dij] = find(A(:,jprev));
if isempty(i)
break
end
I = [i, du(j)+dij, jprev(j)];
I = sortrows(I, [1 2]);
dI = diff([0 0; I(:,1:2)],1,1) ~= 0;
change = find(dI(:,1)|dI(:,2));
Ic = I(change,:);
b = dI(change,1) & (Ic(:,2) <= d(Ic(:,1)));
lgt = diff([change; size(dI,1)+1],1,1);
I = I(repelem(b, lgt),:);
if isempty(I)
break
end
lgtk = lgt(b);
istart = cumsum([1; lgtk]);
istop = istart(2:end)-1;
istart(end) = [];
jprev = cell(size(istart));
j = I(:,3);
for k=1:size(jprev)
jprev{k} = j(istart(k):istop(k));
end
i = I(istart,1);
du = I(istart,2);
neq = du < d(i);
if all(neq)
prev(i) = jprev;
else
prev(i(neq)) = jprev(neq);
eq = ~neq;
ieq = i(eq);
prev(ieq) = cellfun(@union, prev(ieq), jprev(eq), 'unif', 0);
end
end
spath = cell(size(prev));
spath{start} = {start};
[neig, k] = sort(neig);
k = k(2:find(isfinite(neig),1,'last'));
for n = k
spath{n} = cellfun(@(p) [p,n], cat(1, spath{prev{n}}), 'unif', 0);
end
end
end
0 Comments
Sign in to comment.