-
Notifications
You must be signed in to change notification settings - Fork 16
/
scomponents.m
73 lines (68 loc) · 2.43 KB
/
scomponents.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
function [sci sizes] = scomponents(A)
% SCOMPONENTS Compute the strongly connected components of a graph
%
% ci=scomponents(A) returns an index for the component number of every
% vertex in the graph A. The total number of components is max(ci).
% If the input is undirected, then this algorithm outputs just the
% connected components. Otherwise, it output the strongly connected
% components.
%
% The implementation is from Tarjan's 1972 paper: Depth-first search and
% linear graph algorithms. In SIAM's Journal of Computing, 1972, 1,
% pp.146-160.
%
% See also DMPERM
%
% Example:
% load_gaimc_graph('cores_example'); % the graph A has three components
% ci = scomponents(A)
% ncomp = max(ci) % should be 3
% R = sparse(1:size(A,1),ci,1,size(A,1),ncomp); % create a restriction matrix
% CG = R'*A*R; % create the graph with each component
% % collapsed into a single node.
% David F. Gleich
% Copyright, Stanford University, 2008-2009
% History
% 2008-04-11: Initial coding
if isstruct(A), rp=A.rp; ci=A.ci; %ofs=A.offset;
else [rp ci]=sparse_to_csr(A);
end
n=length(rp)-1; sci=zeros(n,1); cn=1;
root=zeros(n,1); dt=zeros(n,1); t=0;
cs=zeros(n,1); css=0; % component stack
rs=zeros(2*n,1); rss=0; % recursion stack holds two nums (v,ri)
% start dfs at 1
for sv=1:n
v=sv; if root(v)>0, continue; end
rss=rss+1; rs(2*rss-1)=v; rs(2*rss)=rp(v); % add v to the stack
root(v)=v; sci(v)=-1; dt(v)=t; t=t+1;
css=css+1; cs(css)=v; % add w to component stack
while rss>0
v=rs(2*rss-1); ri=rs(2*rss); rss=rss-1; % pop v from the stack
while ri<rp(v+1)
w=ci(ri); ri=ri+1;
if root(w)==0
root(w)=w; sci(w)=-1; dt(w)=t; t=t+1;
css=css+1; cs(css)=w; % add w to component stack
rss=rss+1; rs(2*rss-1)=v; rs(2*rss)=ri; % add v to the stack
v=w; ri=rp(w); continue;
end
end
for ri=rp(v):rp(v+1)-1
w=ci(ri);
if sci(w)==-1
if dt(root(v))>dt(root(w)), root(v)=root(w); end
end
end
if root(v)==v
while css>0
w=cs(css); css=css-1; sci(w)=cn;
if w==v, break; end
end
cn=cn+1;
end
end
end
if nargout>1
sizes=accumarray(sci,1,[max(sci) 1]);
end