I want you to examine the following 2 programs very carefully, then i will ask some questions.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include "MinHeap.h"
using namespace std;

struct Word{
    string word;
    int f, g, h; //values
    
    Word (const string& w, int g_, int h_) : word(w), g(g_), h(h_) {
        f = g + h;
    }

    bool operator<(const Word& other) const {
        if (f != other.f) {
            return f < other.f;
        }
        if (h != other.h) {
            return h < other.h;
        }
        return word < other.word;
    }
    
};


int heuristic(const string& curr, const string& target) {
    int count = 0;
    for (size_t i = 0; i < curr.length(); i++) {
        if (curr[i] != target[i]) {
            count++;
        }
    }
    return count;
}


vector<string> nextWords(const string& curr, const unordered_set<string>& wordSet){
    vector <string> nextWords;
    for (size_t i = 0; i < curr.length(); i++) {
        for (char c = 'a'; c <= 'z'; c++) {
            string word = curr;
            word[i] = c;
            if (wordSet.find(word) != wordSet.end()) {
                nextWords.push_back(word);
            }
        }
    }
    return nextWords;
}


pair<int,int> Search(const string& start, const string& target, const unordered_set<string>& wordSet) {
    MinHeap<Word> heap(2); //binary heap for efficiency
    Word first(start, 0, heuristic(start, target));
    int priority = first.f * (first.word.size() + 1) + first.h; //p = f*(n+1)+1
    heap.add(first, priority); //add first word to heap

    unordered_set <string> visited; //keep track of visited words
    int expansion = -1;

    while(!heap.isEmpty()) {
        //get the word with the lowest f value
        Word curr = heap.peek();
        heap.remove();

        
        if (visited.find(curr.word) != visited.end()) { //already visited, move to next word
            continue;
        }
        
        expansion++;
        visited.insert(curr.word);
        
        if (curr.word == target) { //target found
            return make_pair(expansion, curr.g);
        }

        vector<string> newWord = nextWords(curr.word, wordSet);
        for (size_t i = 0; i < newWord.size(); i++) {
            int g = curr.g + 1;
            int h = heuristic(newWord[i], target);
            Word next(newWord[i], g, h);
            int p = next.f * (next.word.size() + 1) + next.h;
            heap.add(next, p);
        }
    }

    return make_pair(expansion, -1); //target not found
}

string convToLower(string src) //helper
{
    std::transform(src.begin(), src.end(), src.begin(), ::tolower);
    return src;
}



int main(int argc, char *argv[]) {
    if (argc != 4){
        cout << "not enough arguments" << endl;
        return 1;
    }

    string startWord = convToLower(argv[1]);
    string endWord = convToLower(argv[2]);
    string wordList = argv[3];

    ifstream file(wordList);
    string word;
    
    int n;
    file >> n; //get number of words
    unordered_set<string> wordSet;
    for (int i = 0; i < n; i++) {
        file >> word;
        wordSet.insert(convToLower(word));
    }
    file.close();

    pair<int,int> result = Search(startWord, endWord, wordSet);
    if (result.second == -1){
        cout << "No transformation" << endl;
        cout << result.first << endl;
    }   else{
        cout << result.second << endl;
        cout << result.first << endl;
    }

    return 0;
}


#ifndef MINHEAP_H
#define MINHEAP_H
#include <vector>
   
template <class T>
struct Heap { //struct to hold heaps data and priority
    T data;
    int priority;
    Heap(T d, int prio) :  data(d), priority(prio) {};

    bool  operator < (const Heap &other) const {  
        return data < other.data;
    };
};

template <class T>
class MinHeap {
    public:
        MinHeap(int d);
        /* Constructor that builds a d-ary Min Heap
        This should work for any d >= 2,
        but doesn't have to do anything for smaller d.*/
        ~MinHeap();

        void add(const T& data, int priority);
        /* adds the item to the heap, with the given priority. */

        const T & peek() const;
        /* returns the element with smallest priority.  
        Break ties however you wish.  
        Throws an exception if the heap is empty. */

        void remove();
        /* removes the element with smallest priority.
        Break ties however you wish.
        Throws an exception if the heap is empty. */

        bool isEmpty();
        /* returns true iff there are no elements on the heap. */

    private:
        // whatever you need to naturally store things.
        // You may also add helper functions here.
        std::vector<Heap<T>> heap_; //store heaps
        int d_; //d-ary

        void bubbleUp (size_t i);
        void trickleDown (size_t i);        
};


 //implementatition
template <class T>
MinHeap<T>::MinHeap (int d) : d_(d) {
    if (d <2){ //check for invalid d
        throw ("d must be greater than 2");
    }
}

template <class T>
MinHeap<T>::~MinHeap() {} //no dynamic mem


template <class T>
void MinHeap<T>::add(const T& data, int priority) {
    //create a new help and add to back
    Heap<T> newHeap(data, priority);
    heap_.push_back(newHeap);

    bubbleUp(heap_.size()-1); //maintain heap property
}

template <class T>
const T& MinHeap<T>::peek() const {
    if (heap_.empty()) {
        throw ("Heap is empty");
    }
    return heap_[0].data; 
}

template <class T>
void  MinHeap<T>::remove() {
    if (heap_.empty()) {
        throw ("Heap is empty");
    }

    //swap  root with last element then remove root
    heap_[0] = heap_[heap_.size()-1];
    heap_.pop_back();

    trickleDown(0); //maintain heap property
}

template <class T>
bool MinHeap<T>::isEmpty() {
    return heap_.empty();
}

template <class T>
void  MinHeap<T>::bubbleUp(size_t i) {
    if (i>0){ //if priority equals then compare word
        if (heap_[i].priority < heap_[(i-1)/d_].priority) {
            std::swap(heap_[i], heap_[(i-1)/d_]);
            bubbleUp((i-1)/d_);
        }
    }
}

template <class T>
void MinHeap<T>::trickleDown(size_t i) {
    size_t child = d_*i + 1;
    if (child >=  heap_.size()) { //check if there is children
        return;
    }    

    //since there are many children, find the smallest child
    size_t minChild = child;
    for (size_t j = child+1; j < heap_.size()  && j < child + d_; j++) { //if priority equals then compare word
        if(heap_[j].priority < heap_[minChild].priority) {
            minChild = j;
        }
    }
    
    //if priority equals then compare word
    if (heap_[minChild].priority < heap_[i].priority) {
        std::swap(heap_[minChild], heap_[i]);
        trickleDown(minChild);
    }
}
   #endif