68 bool TryAdd(
int x,
int y, int64_t coeff, int64_t offset);
72 bool TryAdd(
int x,
int y, int64_t coeff, int64_t offset,
bool allow_rep_x,
91 Relation
Get(
int x)
const;
98 if (
x >= size_.size())
return;
99 CHECK_NE(size_[
x], kSizeForRemovedEntry) <<
x;
102 CHECK_GT(size_[r], 1);
105 CHECK_EQ(size_[r], 1);
107 size_[
x] = kSizeForRemovedEntry;
112 if (
x >= representative_.size())
return 1;
117 const int kSizeForRemovedEntry = 0;
119 void IncreaseSizeOfMemberVectors(
int new_size) {
120 if (new_size <= representative_.size())
return;
121 for (
int i = representative_.size(); i < new_size; ++i) {
122 representative_.push_back(i);
124 offset_.resize(new_size, 0);
125 coeff_.resize(new_size, 1);
126 size_.resize(new_size, 1);
129 void CompressPath(
int x)
const {
131 DCHECK_LT(
x, representative_.size());
134 while (parent != representative_[parent]) {
135 tmp_path_.push_back(parent);
136 parent = representative_[parent];
139 const int old_parent = representative_[
var];
140 offset_[
var] += coeff_[
var] * offset_[old_parent];
141 coeff_[
var] *= coeff_[old_parent];
142 representative_[
var] = parent;
149 mutable std::vector<int> representative_;
153 mutable std::vector<int64_t> coeff_;
154 mutable std::vector<int64_t> offset_;
162 std::vector<int> size_;
165 mutable std::vector<int> tmp_path_;
174 bool allow_rep_x,
bool allow_rep_y) {
179 IncreaseSizeOfMemberVectors(std::max(
x,
y) + 1);
180 CHECK_NE(size_[
x], kSizeForRemovedEntry) <<
x;
181 CHECK_NE(size_[
y], kSizeForRemovedEntry) <<
y;
184 const int rep_x = representative_[
x];
185 const int rep_y = representative_[
y];
186 if (rep_x == rep_y)
return false;
191 const int64_t coeff_x = coeff_[
x];
192 const int64_t new_coeff = coeff * coeff_[
y];
193 const int64_t new_offset = coeff * offset_[
y] + offset - offset_[
x];
194 const bool condition1 =
195 allow_rep_y && (new_coeff % coeff_x == 0) && (new_offset % coeff_x == 0);
196 const bool condition2 = allow_rep_x && (coeff_x % new_coeff == 0) &&
197 (new_offset % new_coeff == 0);
198 if (condition1 && (!condition2 || size_[
x] <= size_[
y])) {
199 representative_[rep_x] = rep_y;
200 size_[rep_y] += size_[rep_x];
201 coeff_[rep_x] = new_coeff / coeff_x;
202 offset_[rep_x] = new_offset / coeff_x;
203 }
else if (condition2) {
204 representative_[rep_y] = rep_x;
205 size_[rep_x] += size_[rep_y];
206 coeff_[rep_y] = coeff_x / new_coeff;
207 offset_[rep_y] = -new_offset / new_coeff;