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 namespace oln
00030 {
00031 namespace morpho
00032 {
00033 namespace slow
00034 {
00035 template <class I, class D, class Env>
00036 template <class N>
00037 f_tarjan_map<I, D, Env>::f_tarjan_map(bool is_closing,
00038 const typename f_tarjan_map<I, D, Env>::input_type& input,
00039 const abstract::neighborhood<N>& ng,
00040 const typename f_tarjan_map<I, D, Env>::lambda_type& lambda,
00041 const Env & env) :
00042 is_closing(is_closing),
00043 input(input),
00044 lambda(lambda),
00045 parent(input.size()),
00046 is_proc(input.size()),
00047 output(input.size()),
00048 env(env)
00049 {
00050
00051 typedef typename std::vector<point_type> vector_type;
00052 vector_type S(input.npoints());
00053 if (is_closing)
00054 utils::distrib_sort(input, S);
00055 else
00056 utils::distrib_sort_inv(input, S);
00057
00058 level::fill(parent, inactive());
00059 level::fill(is_proc, false);
00060
00061
00062 make_set(S[0]);
00063 is_proc[S[0]] = true;
00064
00065 for (int ip = 1; ip < int(S.size()); ++ip)
00066 {
00067 point_type p = S[ip];
00068
00069
00070 point_type p_ = S[ip - 1];
00071 if (input[p] != input[p_])
00072 {
00073
00074 for (int iq = ip - 1; iq >= 0; --iq)
00075 {
00076 point_type q = S[iq];
00077 if (input[q] != input[p_])
00078 break;
00079
00080
00081 if (parent[q] == active() && !(auxdata[q] < lambda))
00082 {
00083 parent[q] = inactive();
00084 auxdata.erase(q);
00085 }
00086 }
00087 }
00088 make_set(p);
00089
00090 oln_neighb_type(N) n(ng, p);
00091 for_all(n)
00092 if (input.hold(n) && is_proc[n])
00093 do_union(n, p);
00094
00095 is_proc[p] = true;
00096 }
00097
00098
00099
00100 for (int ip = int(S.size()) - 1; ip >= 0; --ip)
00101 {
00102 point_type p = S[ip];
00103 if (parent[p] == active() || parent[p] == inactive())
00104 output[p] = input[p];
00105 else
00106 output[p] = output[parent[p]];
00107 }
00108 }
00109
00110 template <class I, class D, class Env>
00111 const typename f_tarjan_map<I, D, Env>::point_type
00112 f_tarjan_map<I, D, Env>::inactive()
00113 {
00114 static const point_type it = utils::internal::mk_point_looking_like<point_type>(-2);
00115 return it;
00116 }
00117
00118 template <class I, class D, class Env>
00119 const typename f_tarjan_map<I, D, Env>::point_type
00120 f_tarjan_map<I, D, Env>::active()
00121 {
00122 static const point_type it = utils::internal::mk_point_looking_like<point_type>(-1);
00123 return it;
00124 }
00125
00126 template <class I, class D, class Env>
00127 void
00128 f_tarjan_map<I, D, Env>::make_set(const typename f_tarjan_map<I, D, Env>::point_type& x)
00129 {
00130 precondition(parent[x] == inactive());
00131 parent[x] = active();
00132 auxdata[x] = D(input, x, env);
00133 }
00134
00135 template <class I, class D, class Env>
00136 void
00137 f_tarjan_map<I, D, Env>::link(const typename f_tarjan_map<I, D, Env>::point_type& x,
00138 const typename f_tarjan_map<I, D, Env>::point_type& y)
00139 {
00140 if (parent[x] == active() && parent[y] == active())
00141 {
00142 auxdata[y] += auxdata[x];
00143 auxdata.erase(x);
00144 }
00145 else
00146 if (parent[x] == active())
00147 auxdata.erase(x);
00148 else
00149 {
00150 parent[y] = inactive();
00151 auxdata.erase(y);
00152 }
00153 parent[x] = y;
00154 }
00155
00156 template <class I, class D, class Env>
00157 typename f_tarjan_map<I, D, Env>::point_type
00158 f_tarjan_map<I, D, Env>::find_root(const typename f_tarjan_map<I, D, Env>::point_type& x)
00159 {
00160 if (parent[x] != active() && parent[x] != inactive())
00161 {
00162 parent[x] = find_root(parent[x]);
00163 return parent[x];
00164 }
00165 return x;
00166 }
00167
00168 template <class I, class D, class Env>
00169 bool
00170 f_tarjan_map<I, D, Env>::equiv(const typename f_tarjan_map<I, D, Env>::point_type& x,
00171 const typename f_tarjan_map<I, D, Env>::point_type& y) const
00172 {
00173 return input[x] == input[y] || parent[x] == active();
00174 }
00175
00176 template <class I, class D, class Env>
00177 void
00178 f_tarjan_map<I, D, Env>::do_union(const typename f_tarjan_map<I, D, Env>::point_type& n,
00179 const typename f_tarjan_map<I, D, Env>::point_type& p)
00180 {
00181 point_type r = find_root(n);
00182 if (r != p)
00183 {
00184 if (equiv(r, p))
00185 link(r, p);
00186 else
00187 if (parent[p] == active())
00188 {
00189 parent[p] = inactive();
00190 auxdata.erase(p);
00191 }
00192 }
00193 }
00194 }
00195 }
00196 }
00197