# Evaluate Division  Difficulty Level Medium
Graph Union Find

In evaluate division problem we have given some equations, in the form, A/B = k, where A and B are strings and k is a real number. Answer some queries, if the answer does not exist return -1.

## Example  Input:
equations: a/b = 2.0 and b/c = 3.0
queries: a/c = ?, b/a = ?, a/e = ?, a/a = ?, x/x = ?
Output:
{6.0, 0.5, -1.0, 1.0, -1.0}

Equations are represented as list of list of strings, values are represented as array of double and queries are also represented as list_of_list_of strings, that is, for above example, input is represented as

equations = {{“a”, “b”}, {“a”, “c”}}
values = {2.0, 3.0}
queries = {{“a”, “c”}, {“b”, “a”}, {“a”, “e”}, {“a”, “a”}, {“x”, “x”}}

## Algorithm for Evaluate Division  The above problem represents a graph.
Variables in the equations are nodes and the value of equations is the weight of edges.
An edge from vertex x to vertex y has a weight equals to x / y.
The graph for the above example is, Answer to a query is found by doing a DFS search in the graph.

1. Build the graph as mentioned above.
2. Each query is of the form of source and destination, we have to start from the source and reach the destination.
3. For every query, start from the source, if the source does not exists, return -1.
4. If the source has a direct edge to the required destination, return the value of the edge.
5. Else mark source as visited and recur for all the neighbors of source that are not visited yet, neighbor becomes the source and destination remains the same, if the answer of any of the neighbor is not -1, return edge weight from source to the neighbor plus answer of neighbor.
Insert Delete GetRandom

## JAVA Code for Evaluate Division  ```import java.util.*;

public class EvaluateDivision {
private static double[] calcEquation(List<List<String>> equations, double[] values,
List<List<String>> queries) {
// Build the graph
HashMap<String, HashMap<String, Double>> graph = new HashMap<>();
for (int i = 0; i < equations.size(); i++) {
String from = equations.get(i).get(0);
String to = equations.get(i).get(1);

// From source to destination the weight of edge is values[i]
if (graph.containsKey(from)) {
graph.get(from).put(to, values[i]);
} else {
HashMap<String, Double> map = new HashMap<>();
map.put(to, values[i]);
graph.put(from, map);
}

// From destination to source the weight of edge is (1 / values[i])
if (graph.containsKey(to)) {
graph.get(to).put(from, 1 / values[i]);
} else {
HashMap<String, Double> map = new HashMap<>();
map.put(from, 1 / values[i]);
graph.put(to, map);
}
}

// Solve queries
double ans[] = new double[queries.size()];
for (int i = 0; i < queries.size(); i++) {
// Visited set
HashSet<String> visited = new HashSet<>();
ans[i] = dfs(graph, queries.get(i).get(0), queries.get(i).get(1), visited);
}

return ans;
}

private static double dfs(HashMap<String, HashMap<String, Double>> graph, String from, String to,
HashSet<String> visited) {
if (!graph.containsKey(from)) {
return -1.0;
}

// Direct edge
if (graph.get(from).containsKey(to)) {
return graph.get(from).get(to);
}

// Mark source as visited

for (Map.Entry<String, Double> entry : graph.get(from).entrySet()) {
if (!visited.contains(entry.getKey())) {
// For all unvisited neighbors of source do dfs
// neighbor becomes the source and destination remains same
double ans = dfs(graph, entry.getKey(), to, visited);
if (ans != -1.0) {
// If ans of any neighbor is not -1, return (edge weight * ans of neighbor)
return (ans * entry.getValue());
}
}
}

// All neighbors returned -1, return -1
return -1.0;
}

public static void main(String[] args) {
// Example
List<List<String>> equations = new ArrayList<>();
ArrayList<String> eq1 = new ArrayList<>();
ArrayList<String> eq2 = new ArrayList<>();

double values[] = new double;
values = 2.0;
values = 3.0;

List<List<String>> queries = new ArrayList<>();
ArrayList<String> q1 = new ArrayList<>();
ArrayList<String> q2 = new ArrayList<>();
ArrayList<String> q3 = new ArrayList<>();
ArrayList<String> q4 = new ArrayList<>();
ArrayList<String> q5 = new ArrayList<>();

double ans[] = calcEquation(equations, values, queries);
for (int i = 0; i < ans.length; i++) {
System.out.print(ans[i] + " ");
}
}
}```

## C++ Code for Evaluate Division  ```#include<bits/stdc++.h>
using namespace std;

double dfs(unordered_map<string, unordered_map<string, double>> &graph,
string from, string to, unordered_set<string> &visited) {
if (graph.find(from) == graph.end()) {
return -1.0;
}

// Direct edge
if (graph[from].find(to) != graph[from].end()) {
return graph[from][to];
}

// Mark source as visited
visited.insert(from);

for (auto i : graph[from]) {
if (visited.find(i.first) == visited.end()) {
// For all unvisited neighbors of source do dfs
double ans = dfs(graph, i.first, to, visited);
if (ans != -1.0) {
// If ans of any neighbor is not -1, return (edge weight * ans of neighbor)
return (ans * i.second);
}
}
}

// All neighbors returned -1, return -1
return -1.0;
}

vector<double> calcEquation(vector<vector<string>>& equations,
vector<double>& values,
vector<vector<string>>& queries) {
// Build the graph
unordered_map<string, unordered_map<string, double>> graph;
for (int i = 0; i < equations.size(); i++) {
string from = equations[i];
string to = equations[i];

// From source to destination the weight of edge is values[i]
if (graph.find(from) == graph.end()) {
unordered_map<std::string, double> m;
m.insert(make_pair(to, values[i]));
graph.insert(make_pair(from, m));
} else {
graph[from].insert(make_pair(to, values[i]));
}

// From destination to source the weight of edge is (1 / values[i])
if (graph.find(to) == graph.end()) {
unordered_map<std::string, double> m;
m.insert(make_pair(from, 1 / values[i]));
graph.insert(make_pair(to, m));
} else {
graph[to].insert(make_pair(from, 1 / values[i]));
}
}

// Solve queries
vector<double> ans;
for (int i = 0; i < queries.size(); i++) {
unordered_set<string> visited;
ans.push_back(dfs(graph, queries[i], queries[i], visited));
}
return ans;
}

int main() {
// Example
vector<vector<string>> equations;
vector<string> eq1;
eq1.push_back("a");
eq1.push_back("b");
equations.push_back(eq1);
vector<string> eq2;
eq2.push_back("b");
eq2.push_back("c");
equations.push_back(eq2);

vector<double> values;
values.push_back(2.0);
values.push_back(3.0);

vector<vector<string>> queries;
vector<string> q1;
q1.push_back("a");
q1.push_back("c");
queries.push_back(q1);
vector<string> q2;
q2.push_back("b");
q2.push_back("a");
queries.push_back(q2);
vector<string> q3;
q3.push_back("a");
q3.push_back("e");
queries.push_back(q3);
vector<string> q4;
q4.push_back("a");
q4.push_back("a");
queries.push_back(q4);
vector<string> q5;
q5.push_back("x");
q5.push_back("x");
queries.push_back(q5);

vector<double> ans = calcEquation(equations, values, queries);
for (int i = 0; i < ans.size(); i++) {
cout<<ans[i]<<" ";
}

return 0;
}```
`6 0.5 -1 1 -1`

## Complexity Analysis  Time Complexity = O(q * (V + E)), where
q –> Number of queries
V –> Number of vertices in the graph(or number of variables)
E –> Number of edges in the graph(or number of equations)