Representing an adjacency list (graph) using a hash table of lists
General Comments

Write your code for readability.

You don't normally see templates written like this:

template &lt;typename T, typename K&gt; void printGraph(graph&lt;T, K&gt;&amp; g)


It pushes the information you want all the way to the right. Normally, I would expect to see the template code on the first line, followed by the object it templates (looking like a normal bit of code):

template &lt;typename T, typename K&gt;
void printGraph(graph&lt;T, K&gt;&amp; g)


The space between &gt; when closing a template has not been needed in over 5 years. Let it be consigned to the big bit bucket in the sky.

 list&lt;pair&lt;T, K&gt; &gt; &gt;


I notice your lack of using std:: when declaring your types.

 unordered_map&lt; T, list


This not only means you have using namespace std; in your code, but that you have it in a header file (or you have a lot of using XXXX; but causes the same issues). The use of using namespace std; in normal code is considered bad practice. But the use of it in a header file is so bad that people will ban your code from projects. You are basically infecting any code that includes your header. This can lead to subtle, impossible-to-find errors. Don't do it.

I would also prefer if you would use an initial capital letter for type information. The most important part of C++ is the type system. Being able to identify types easily is essential. Thus, most people use an initial capital letter to identify user-defined types, while an initial lower-case letter identifies an object.

Build your types from smaller types. This will make it easier to maintain your code as it localizes changes. For example, rather than using std::pair&lt;T, K&gt; as your edge definition, prefer to use a named type Edge. That way, if you change the definition of the type, you only have to change it in a single location and not trawl through your code looking for all uses. Also, using a name like that provides context and meaning, which in turn makes your code easier to read.

template &lt;typename T, typename K&gt;
struct Graph
{
    using Edge        = std::pair&lt;T, K&gt;;
    using EdgeList    = std::list&lt;Edge&gt;;
    using AdjencyList = std::unordered_map&lt;T, EdgeList&gt;;

    AdjencyList adjList;
    bool        directed = true; // use real bool(s) not int.
};


Design Comments

You are completely ignoring encapsulation. Your functions may work, but because your data is completely exposed, there is no protection from a bad coder coming along and breaking your constraints. Your methods are supposed to be the only way to manipulate the state (so it can be controlled).

Because of this, your code would fail any competent code review and not be allowed into the code base.