<p>You are given two <strong>0-indexed</strong> strings <code>source</code> and <code>target</code>, both of length <code>n</code> and consisting of <strong>lowercase</strong> English letters. You are also given two <strong>0-indexed</strong> character arrays <code>original</code> and <code>changed</code>, and an integer array <code>cost</code>, where <code>cost[i]</code> represents the cost of changing the character <code>original[i]</code> to the character <code>changed[i]</code>.</p>

<p>You start with the string <code>source</code>. In one operation, you can pick a character <code>x</code> from the string and change it to the character <code>y</code> at a cost of <code>z</code> <strong>if</strong> there exists <strong>any</strong> index <code>j</code> such that <code>cost[j] == z</code>, <code>original[j] == x</code>, and <code>changed[j] == y</code>.</p>

<p>Return <em>the <strong>minimum</strong> cost to convert the string </em><code>source</code><em> to the string </em><code>target</code><em> using <strong>any</strong> number of operations. If it is impossible to convert</em> <code>source</code> <em>to</em> <code>target</code>, <em>return</em> <code>-1</code>.</p>

<p><strong>Note</strong> that there may exist indices <code>i</code>, <code>j</code> such that <code>original[j] == original[i]</code> and <code>changed[j] == changed[i]</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> source = &quot;abcd&quot;, target = &quot;acbe&quot;, original = [&quot;a&quot;,&quot;b&quot;,&quot;c&quot;,&quot;c&quot;,&quot;e&quot;,&quot;d&quot;], changed = [&quot;b&quot;,&quot;c&quot;,&quot;b&quot;,&quot;e&quot;,&quot;b&quot;,&quot;e&quot;], cost = [2,5,5,1,2,20]
<strong>Output:</strong> 28
<strong>Explanation:</strong> To convert the string &quot;abcd&quot; to string &quot;acbe&quot;:
- Change value at index 1 from &#39;b&#39; to &#39;c&#39; at a cost of 5.
- Change value at index 2 from &#39;c&#39; to &#39;e&#39; at a cost of 1.
- Change value at index 2 from &#39;e&#39; to &#39;b&#39; at a cost of 2.
- Change value at index 3 from &#39;d&#39; to &#39;e&#39; at a cost of 20.
The total cost incurred is 5 + 1 + 2 + 20 = 28.
It can be shown that this is the minimum possible cost.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> source = &quot;aaaa&quot;, target = &quot;bbbb&quot;, original = [&quot;a&quot;,&quot;c&quot;], changed = [&quot;c&quot;,&quot;b&quot;], cost = [1,2]
<strong>Output:</strong> 12
<strong>Explanation:</strong> To change the character &#39;a&#39; to &#39;b&#39; change the character &#39;a&#39; to &#39;c&#39; at a cost of 1, followed by changing the character &#39;c&#39; to &#39;b&#39; at a cost of 2, for a total cost of 1 + 2 = 3. To change all occurrences of &#39;a&#39; to &#39;b&#39;, a total cost of 3 * 4 = 12 is incurred.
</pre>

<p><strong class="example">Example 3:</strong></p>

<pre>
<strong>Input:</strong> source = &quot;abcd&quot;, target = &quot;abce&quot;, original = [&quot;a&quot;], changed = [&quot;e&quot;], cost = [10000]
<strong>Output:</strong> -1
<strong>Explanation:</strong> It is impossible to convert source to target because the value at index 3 cannot be changed from &#39;d&#39; to &#39;e&#39;.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= source.length == target.length &lt;= 10<sup>5</sup></code></li>
	<li><code>source</code>, <code>target</code> consist of lowercase English letters.</li>
	<li><code>1 &lt;= cost.length == original.length == changed.length &lt;= 2000</code></li>
	<li><code>original[i]</code>, <code>changed[i]</code> are lowercase English letters.</li>
	<li><code>1 &lt;= cost[i] &lt;= 10<sup>6</sup></code></li>
	<li><code>original[i] != changed[i]</code></li>
</ul>

class Solution
{
private:
    const long long int INF = 1e12;
    // Dijkstra's algorithm to find the shortest path from 'start' to all other nodes
    void dijkstra(char start, unordered_map<char, vector<pair<char, long long int>>> &adj, unordered_map<char, unordered_map<char, long long int>> &helper)
    {

        unordered_map<char, long long int> dist;
        for (char ch = 'a'; ch <= 'z'; ch++)
        {
            dist[ch] = INF;
        }
        dist[start] = 0;

        priority_queue<pair<long long int, char>> pq; //min heap
        pq.push({-0, start});

        while (!pq.empty())
        {
            long long int currDist = -pq.top().first;
            char currNode = pq.top().second;
            pq.pop();

            if (currDist > dist[currNode])
            {
                continue;
            }
            for (auto &edge : adj[currNode])
            {
                char next_node = edge.first;
                long long int edge_cost = edge.second;

                if (dist[currNode] + edge_cost < dist[next_node])
                {
                    dist[next_node] = dist[currNode] + edge_cost;
                    pq.push({-dist[next_node], next_node});
                }
            }
        }
        //setiing the helper with the optimal distances to all other nodes.
        helper[start] = dist;
    }

public:
    long long minimumCost(string source, string target, vector<char> &original, vector<char> &changed, vector<int> &cost)
    {

        if (source.size() != target.size())
            return -1;

        // 1. setting the requirements
        unordered_map<char, vector<char>> req;
        for (int i = 0; i < source.size(); i++)
        {
            if (source[i] != target[i])
            {
                req[source[i]].push_back(target[i]);
            }
        }

        // 2. Making the adjacency list for our directed weighted graph
        unordered_map<char, vector<pair<char, long long int>>> adj;
        for (int i = 0; i < original.size(); i++)
        {
            adj[original[i]].push_back({changed[i], cost[i]});
        }


        long long ans = 0;
        // 3. calling the helper function to get the optimal distances to all other nodes.
        unordered_map<char, unordered_map<char, long long int>> helper;
        for (auto &x : req)
        {
            // 4. using Dijkstra algorithm to find the  optimal distance if path for cuurrent node is not present in the helper.
            if (helper.find(x.first) == helper.end())
            {
                dijkstra(x.first, adj, helper);
                cout << "calling for " << x.first << "-> ";
                for (auto y : helper[x.first])
                    cout << y.first << " : " << y.second << " \n";
            }
            for (char ch : x.second)
            {
                if (helper[x.first].find(ch) != helper[x.first].end())
                {
                    //6. if no path is found distance will reamin infiinite
                    if (helper[x.first][ch] == INF) 
                        return -1;
                    // else add the distance to ans
                    ans += helper[x.first][ch];
                }
                else
                {
                    return -1; // if there's no path to convert a character
                }
            }
        }

        // optimal path found
        return ans;
    }
};
133185