-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
check-for-contradictions-in-equations.cpp
114 lines (106 loc) · 3.5 KB
/
check-for-contradictions-in-equations.cpp
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Time: O(e + q)
// Space: O(n)
// union find
class Solution {
public:
bool checkContradictions(vector<vector<string>>& equations, vector<double>& values) {
static const double EPS = 1e-5;
UnionFind uf;
for (int i = 0; i < size(equations); ++i) {
if (!uf.union_set(equations[i][0], equations[i][1], values[i]) &&
abs(uf.query_set(equations[i][0], equations[i][1]) - values[i]) > EPS) {
return true;
}
}
return false;
}
private:
class UnionFind {
public:
UnionFind() {
}
pair<string, double> find_set(const string& x) {
if (!set_.count(x)) {
set_[x] = pair(x, 1.0);
}
const auto& [xp, xr] = set_[x];
if (x != xp) {
const auto& [pp, pr] = find_set(xp); // Path compression.
set_[x] = pair(pp, xr * pr);
}
return set_[x];
}
bool union_set(const string& x, const string& y, double r) {
const auto& [xp, xr] = find_set(x);
const auto& [yp, yr] = find_set(y);
if (xp == yp) {
return false;
}
if (rank_[xp] < rank_[yp]) { // Union by rank.
set_[xp] = pair(yp, r * yr / xr);
} else if (rank_[xp] > rank_[yp]) {
set_[yp] = pair(xp, 1.0 / r * xr / yr);
} else {
set_[yp] = pair(xp, 1.0 / r * xr / yr);
++rank_[xp];
}
return true;
}
double query_set(const string& x, const string& y) {
if (!set_.count(x) || !set_.count(y)) {
return -1.0;
}
const auto& [xp, xr] = find_set(x);
const auto& [yp, yr] = find_set(y);
return (xp == yp) ? xr / yr : -1.0;
}
private:
unordered_map<string, pair<string, double>> set_;
unordered_map<string, int> rank_;
};
};
// Time: O(e + q)
// Space: O(n)
// dfs
class Solution2 {
public:
bool checkContradictions(vector<vector<string>>& equations, vector<double>& values) {
unordered_map<string, vector<pair<string, double>>> adj;
for (int i = 0; i < size(equations); ++i) {
adj[equations[i][0]].emplace_back(equations[i][1], 1.0 / values[i]);
adj[equations[i][1]].emplace_back(equations[i][0], values[i]);
}
unordered_map<string, double> lookup;
const auto& iter_dfs = [&](const auto& u) {
vector<string> stk = {u};
lookup[u] = 1.0;
while (!empty(stk)) {
auto u = stk.back(); stk.pop_back();
for (const auto& [v, k] : adj[u]) {
if (lookup.count(v)) {
if (!isclose(lookup[v], lookup[u] * k)) {
return true;
}
continue;
}
lookup[v] = lookup[u] * k;
stk.emplace_back(v);
}
}
return false;
};
for (const auto& [u, _] : adj) {
if (lookup.count(u)) {
continue;
}
if (iter_dfs(u)) {
return true;
}
}
return false;
}
private:
bool isclose(double a, double b, double rel_tol = 1e-09, double abs_tol = 0.0) {
return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol);
}
};