Disjoint Union Set 並查集

Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return -1.0.

Example:
Given a / b = 2.0, b / c = 3.0.
queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? .
return [6.0, 0.5, -1.0, 1.0, -1.0 ].

The input is: vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries , where equations.size() == values.size(), and the values are positive. This represents the equations. Return vector<double>.

According to the example above:

equations = [ ["a", "b"], ["b", "c"] ],
values = [2.0, 3.0],
queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]. 
 

The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction.

 

The implementation:

/**
 * Author sesiria, 2019
 * Dvaluate Division from LeetCode.399
 */
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>

using namespace std;

class Solution {
private:
    struct dsjSet{
        unordered_map<string, string> graph;
        unordered_map<string, double> weight;
        
        string find(string p) {
            while(graph.count(p) && graph[p] != p) {
                p = graph[p];
            }
            return p;
        }
        
        void addEdge(string from, string to, double value) {            
            if (!weight.count(from)) weight[from] = value, graph[from]= from;
            if (!weight.count(to)) weight[to] = 1.0, graph[to] = to;
            // update values;
            double ratio = value * weight[to] / weight[from];
            
            auto p1 = find(from);
            auto p2 = find(to);
            for (auto & entry : graph) {
                if (find(entry.first) == p1)
                    weight[entry.first] *= ratio;
            }
            // relink the graph
            graph[p1] = p2;
        }
        
        double getWeight(string from, string to) {
            
            if (graph.count(from) == 0 || graph.count(from) == 0)
                return -1.0;
            
            if (find(from) != find(to))
                return -1.0;
            
            return weight[from] / weight[to];
        }
    };
public:
    vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
        dsjSet Graph;
        
        int N = equations.size();
        for (int i = 0; i < N; ++i)
            Graph.addEdge(equations[i][0], equations[i][1], values[i]);
        
        vector<double> result;
        for (auto & query : queries)
            result.push_back(Graph.getWeight(query[0], query[1]));
        
        return result;
    }
};

int main()
{
    vector<vector<string>> equations = {{"x1","x2"},{"x2","x3"},{"x1","x4"},{"x2","x5"}};
    vector<double> values = {3.0,0.5,3.4,5.6};
    vector<vector<string>> queries = {{"x2","x4"},{"x1","x5"},{"x1","x3"},{"x5","x5"},{"x5","x1"},{"x3","x4"},{"x4","x3"},{"x6","x6"},{"x0","x0"}};

    Solution sol;
    auto result = sol.calcEquation(equations, values, queries);

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章