Inputs guarantee only one edge needs to be removed to make the directed graph a tree, so there are only two cases where an edge needs to be deleted:

- An edge that makes a node having more than one parents;
- An edge that cause a loop.

For each edge (u -> v), we firstly check whether the child (v) has already had a parent. If not, only an edge that connect the root and its descendent can make a loop. So we only need to check whether v is u's root.

C++:

```
vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
unordered_map<int, int> parents; // record tree nodes and its parents
for (int i = 0; i < edges.size(); i++) {
if (parents.find(edges[i][1]) != parents.end()) return edges[i]; //more than one parents
int p = edges[i][0]; // finding u's root
while (parents.find(p) != parents.end()) p = parents[p];
if (p == edges[i][1]) return edges[i];
parents[edges[i][1]] = edges[i][0];
}
return {};
}
```

Python:

```
def findRedundantDirectedConnection(self, edges):
parents = {}
for e in edges:
if e[1] in parents: return e
p = e[0]
while p in parents: p = parents[p]
if p == e[1]: return e
parents[e[1]] = e[0]
return []
```