00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #ifndef SGI_connected_components_h_INCLUDED
00042 #define SGI_connected_components_h_INCLUDED
00043
00044 #include "misc_extension.h"
00045 #include <algorithm>
00046
00047 namespace SGI {
00048
00049 template <class NodeIterator, class NodeIndex>
00050 NodeIndex find_representative_and_compress_path(NodeIterator c, NodeIndex current)
00051 {
00052 NodeIndex old = current;
00053 NodeIndex ancestor = c[current];
00054 while (ancestor != current) {
00055 current = ancestor;
00056 ancestor = c[current];
00057 }
00058 current = c[old];
00059 while (ancestor != current) {
00060 c[old] = ancestor;
00061 old = current;
00062 current = c[old];
00063 }
00064 return ancestor;
00065 }
00066
00067 template <class NodeContainer, class RankContainer, class NodeIndex>
00068 inline void extend_components_and_ranks(NodeContainer& c,
00069 RankContainer& rank,
00070 NodeIndex n)
00071 {
00072 typename NodeContainer::size_type needed = n + 1;
00073 if (needed > c.size()) {
00074 typename NodeContainer::size_type old_size = c.size();
00075 rank.insert(rank.end(), (typename RankContainer::size_type)(needed - old_size), (typename RankContainer::value_type)0);
00076 c.insert(c.end(), int_iterator<NodeIndex>(old_size), int_iterator<NodeIndex>(needed));
00077 }
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 template <class NodeIterator, class RankIterator, class NodeIndex>
00089 inline void connect_components(NodeIterator component,
00090 RankIterator rank,
00091 NodeIndex i,
00092 NodeIndex j)
00093 {
00094 i = find_representative_and_compress_path(component, i);
00095 j = find_representative_and_compress_path(component, j);
00096 if (i == j) return;
00097 if (rank[i] > rank[j])
00098 component[j] = i;
00099 else {
00100 if (rank[i] == rank[j])
00101 ++rank[j];
00102 component[i] = j;
00103 }
00104 }
00105
00106
00107 template <class Iterator, class NodeContainer>
00108 void construct_connected_components(Iterator f,
00109 Iterator l,
00110 NodeContainer& component)
00111 {
00112 vector<unsigned char> rank;
00113 for (Iterator e = f; e != l; ++e) {
00114 extend_components_and_ranks(component, rank, max(first(*e), second(*e)));
00115 connect_components(component.begin(), rank, first(*e), second(*e));
00116 }
00117 for (typename Iterator::value_type::first_type i = 0; i < component.size(); ++i)
00118 find_representative_and_compress_path(component.begin(), i);
00119
00120
00121 }
00122
00123
00124 template <class Iterator, class NodeContainer, class NodeIndex>
00125 void construct_connected_components(Iterator f,
00126 Iterator l,
00127 NodeContainer& component,
00128 NodeIndex max_node_index)
00129 {
00130 vector<unsigned char> rank;
00131 extend_components_and_ranks(component, rank, max_node_index+1);
00132 for (Iterator e = f; e != l; ++e)
00133 connect_components(component.begin(), rank, first(*e), second(*e));
00134 for (typename Iterator::value_type::first_type i = 0; i < component.size(); ++i)
00135 find_representative_and_compress_path(component.begin(), i);
00136
00137
00138 }
00139
00140 template <class NodeIterator, class NodeIndex>
00141 bool is_connected(NodeIterator component, NodeIndex i, NodeIndex j)
00142 {
00143 return component[i] == component[j];
00144 }
00145
00146 template <class NodeIterator, class NodeIndex>
00147 bool is_connected_and_compress_path(NodeIterator component, NodeIndex i, NodeIndex j)
00148 {
00149 return find_representative_and_compress_path(component, i) ==
00150 find_representative_and_compress_path(component, j);
00151 }
00152
00153
00154 }
00155
00156 #endif
00157
00158
00159
00160
00161