Root the tree arbitrarily. For each vertex , let be the minimum vertex cover size in its descendant subtree, conditional on selecting , and the corresponding minimum conditional on omitting . Process the vertices in postorder traversal. For every child of ,
At a leaf of a rooted tree, the empty sums give . Return at the root .
For algorithm correctness, if is selected, each child subtree may independently use its cheaper state, since the connecting edge is already covered by . If is omitted, each child must be selected to cover its connecting edge. Distinct child subtrees have no edges between them because the input is a tree. These observations prove the recurrences by structural induction. Each edge contributes constant work once, giving time complexity and space with adjacency lists. The single-vertex tree correctly has optimum zero. This is minimum vertex cover of a tree by dynamic programming.
The vertex cover decision problem takes a finite simple graph and a nonnegative integer , and asks whether there is a vertex cover of cardinality at most . The optimization problem asks for a minimum vertex cover, with cost equal to its cardinality.
For the decision problem, if there are no edges, accept; if there is an edge but , reject. Otherwise choose an edge and branch: either include and recurse on with budget , or include and recurse on with budget . Accept if either branch accepts. Every vertex cover contains at least one endpoint of , so every possible solution is retained by at least one branch. Conversely, adding the selected endpoint to a vertex cover returned by the smaller instance covers all original edges. This proves correctness by induction on the remaining budget.
The search tree has depth at most and at most leaves. Processing each node in time gives running time, establishing fixed-parameter tractability.
For optimization, greedily build a maximal matching : repeatedly select an edge and discard every edge touching either endpoint. Return the set of all endpoints of . Any edge with neither endpoint in could be added to , contradicting maximality; thus is a vertex cover. Since the edges of a matching in a graph have pairwise disjoint endpoint sets, every vertex cover must contain at least one different vertex for each of them. Therefore
The greedy construction takes polynomial time, and can be implemented in with adjacency lists. It needs only a maximal matching, not a maximum matching.
First test for an isolated vertex, reporting infeasibility if one exists. Otherwise compute a maximum cardinality matching using a general-graph polynomial-time algorithm, then add one arbitrary incident edge for each unmatched vertex in a matching. The proof in (i) shows that the resulting edge cover has minimum cardinality .
The final scan takes time with adjacency lists; the maximum cardinality matching computation is polynomial. One may obtain it from a general-graph maximum-weight matching routine with every weight equal to one.[ref]
Use the DAG shortest-path algorithm: first compute a topological ordering, then perform edge relaxation once for every edge in that order. Store a shortest-path predecessor when a distance improves so that the actual paths, as well as their costs, can be recovered.
order := a topological ordering of V;
FOR each vertex v DO d[v] := infinity; pred[v] := NIL END;
d[source] := 0;
FOR u in order DO
  IF d[u] <> infinity THEN
    FOR each edge (u,v) with cost w DO
      IF d[u] + w < d[v] THEN
        d[v] := d[u] + w; pred[v] := u
      END
    END
  END
END
Each loop has a natural invariant. During initialization, all vertices already processed have infinite distance and no predecessor. During the outer relaxation loop, all processed vertices have their final shortest-path distances, and every edge leaving a processed vertex has been relaxed. During an inner edge loop, the outgoing edges of u already inspected have been relaxed using its final distance, while the outer invariant remains true for all earlier vertices.
For correctness, every path to a vertex ends with an edge from an earlier vertex in the topological ordering. When is reached, all those earlier distances are correct and all incoming edges have been relaxed. Therefore
with infinite distance for unreachable vertices and the empty path included at the source. No directed path can return to the source in a Directed acyclic graph. Induction over the topological ordering proves all distances correct. Following predecessor links backward reconstructs each reachable shortest path.
With adjacency lists, topological sorting takes time and the relaxation pass has the same bound, using extra space beyond the input. Thus the full distance and predecessor representation costs time. Printing every source-to-vertex path separately can take more time because their total output length may be quadratic. The stipulated nonnegative costs are sufficient; this algorithm actually also permits negative costs because there are no directed graph cycles.
Use Kahn's algorithm for topological sorting. With an adjacency list representation, count every vertex's indegree by scanning the edges. Put all zero-indegree vertices in a queue. Repeatedly remove one such vertex , append it to the output, and delete its outgoing edges by decrementing the stored indegree of each neighbour; enqueue a neighbour exactly when its count becomes zero.
The loop invariant is that stored counts are the indegrees in the unreported subgraph and the queue contains exactly its unreported zero-indegree vertices. A nonempty finite Directed acyclic graph always has such a vertex: otherwise following incoming edges would eventually repeat a vertex, creating a directed graph cycle. Thus the queue cannot become empty while any vertex remains.
For every original edge , cannot enter the output until that edge has been removed by outputting . Therefore
Each vertex enters and leaves the queue once, and every edge is scanned a constant number of times, giving time and auxiliary space beyond the adjacency lists. If given only an adjacency matrix, scanning neighbours instead takes time.
Use the two-pass strongly connected component algorithm. First run a complete depth-first search of , starting a new search at each unvisited vertex as necessary. Append each vertex to a list when its recursive call finishes. Next construct the graph transpose by reversing every edge. Reset all visited flags. Process the vertices in decreasing first-pass finishing order, running depth-first search in from each still-unvisited vertex. The newly reached vertices in each such search form one strongly connected component.
To prove this, contract each strongly connected component to one vertex. The resulting condensation graph is a Directed acyclic graph, because a directed graph cycle of distinct components would make them mutually reachable and hence a single component. For a component , write for its largest first-pass finishing time. If there is an edge between distinct components, then . Indeed, if the first search reaches before , it can reach , which must finish before the search in finishes. If it reaches first, cannot reach or they would be the same component, so finishes before is discovered.
Among unreported components, the one with greatest therefore has no incoming edge from another unreported component in . In the graph transpose it has no outgoing edge to any other unreported component. A second-pass search cannot escape it, while strong connectivity lets that search reach all its vertices. Earlier reported components are ignored by the visited flags. Repeating this argument proves
Both depth-first searches visit every vertex and scan every edge once, and transposition costs . Therefore the total time complexity is with adjacency lists. Storage for the transpose is , while visited flags, finishing order and the search stack use additional space. No sorting is needed: reverse the list recorded at finishing time.
Choose a root. For each vertex , define as the maximum size in its descendant subtree when is included, and as that size when is excluded. For its children ,
A leaf has . If is included, all its children must be excluded. If is excluded, either child state is allowed. Different child subtrees have no edges between them because the graph is a tree, so their contributions can be optimized independently. This proves the recurrence by structural induction.
Evaluate the two states in postorder traversal. At root , the answer is . For reconstruction, pick an attaining root state; an included vertex forces every child to its excluded state, while an excluded vertex permits each child to choose its larger state. Record the included vertices during this second traversal, breaking ties consistently.
With adjacency lists, rooting, state evaluation and reconstruction each take time, with stored states and output. This is maximum independent set in a tree.
The source describes an independent set as a proper subset. For a tree with at least one edge, every independent set is automatically proper, so the algorithm meets that convention. If it is enforced literally for the single-vertex tree, return the empty set of size zero there; the usual non-strict subset convention would instead return its one vertex.
Depth-first search marks a vertex when first reached, then recursively explores each still-unvisited neighbour before returning. To cover the whole graph, restart from every vertex not reached by earlier searches:
visit(v):
    visited[v] = true
    for w in adjacency[v]:
        if not visited[w]:
            visit(w)

for v in V:
    if not visited[v]:
        visit(v)
For a directed graph, use outgoing neighbours; for an undirected graph, use both incidences of each edge. Each vertex is discovered once and each stored incidence is inspected once. Thus with adjacency lists the running time is and the visited information and recursion stack use space. An adjacency matrix representation instead requires scanning possible neighbours per visited vertex, giving time.
Augment depth-first search with a two-valued colour:
paint(v, c):
    colour[v] = c
    for w in adjacency[v]:
        if colour[w] is unset:
            if not paint(w, 1-c):
                return false
        else if colour[w] == c:
            return false
    return true

for v in V:
    if colour[v] is unset:
        if not paint(v, 0):
            return false
return true
Each tree edge receives opposite endpoint colours. If an inspected edge has equal colours, the preceding parity argument produces an odd cycle, so the graph is not bipartite. If the procedure succeeds, every edge has differently coloured endpoints, and the two colour classes are a bipartition. The outer loop handles disconnected graphs and isolated vertices.
Each vertex is coloured once and each edge incidence is checked once, giving time and extra space with adjacency lists. No separate cycle enumeration is required.
Dijkstra's algorithm solves the single-source shortest-path problem with nonnegative edge weights: it finds minimum path lengths from the source to all reachable vertices and can store predecessor edges. With adjacency lists and a binary-heap priority queue, it takes time; a direct array implementation takes .
The Bellman-Ford algorithm allows negative edge weights. If no negative-weight cycle is reachable from the source, it computes the finite shortest-path distances to reachable vertices and identifies unreachable ones. Otherwise it can report a reachable negative cycle, whose repeated traversal makes distances to some reachable vertices unbounded below. It performs at most full relaxation rounds and one further detection round, taking time, conventionally written for nontrivial edge sets. A negative cycle unreachable from the source does not affect its distance problem.
Process outgoing edges in topological order:
order = topological_sort(G)
for v in V:
    distance[v] = infinity
    predecessor[v] = none
distance[s] = 0

for u in order:
    if distance[u] != infinity:
        for edge (u,v) of weight w:
            if distance[u] + w < distance[v]:
                distance[v] = distance[u] + w
                predecessor[v] = u
For correctness, argue by induction through the topological sort. Every path ending at a vertex reaches it through some incoming edge . All such predecessors occur earlier, so their finalized shortest-path distances have already been considered when is processed. Taking the minimum of over these edges therefore gives exactly the shortest-path distance to . Unreachable vertices retain infinity. Negative edge weights cause no difficulty because a later vertex cannot lead back to an earlier one.
This is the DAG shortest-path algorithm. Topological sorting and the single pass of edge relaxation each take time with adjacency lists; distances, predecessors and the order use auxiliary space. Following predecessors reconstructs a shortest path to any reachable target.
Compute any topological sort using a standard algorithm, then check its consecutive entries in the adjacency matrix:
DAGHamiltonianPath(A):
    order = TopologicalSort(A)
    for j = 1,...,n-1:
        if not A[order[j],order[j+1]]:
            return "no Hamiltonian path"
    return order
If all checks pass, the returned ordering is a Hamiltonian path. If a check fails but a Hamiltonian path existed, part (d) would force the computed topological sort to equal the unique path order, whose consecutive edges all exist. This contradiction proves the negative answer correct.
A standard topological sort scans all matrix rows and therefore takes time with this input representation; the subsequent edge checks take . The answer is consequently time, with auxiliary storage beyond the input matrix. An bound for an adjacency list must not be substituted for the stipulated adjacency matrix bound.
Use an indexed priority queue of unsettled vertices, keyed by their tentative distances. Initialize the source to zero and other keys to . Each ExtractMin settles the currently closest vertex. Scan its outgoing edges; whenever edge relaxation improves a neighbour's tentative distance, update that neighbour with DecreaseKey. Already settled vertices need no further update, by the correctness of Dijkstra's algorithm for nonnegative weights.
There are at most extractions and at most successful decreases. The indexed priority queue maintains each vertex's current array position and updates this index table on every swap, so locating a key for DecreaseKey costs . Preallocate capacity . Repeated insertion costs , or bottom-up heap construction initializes the queue in time. Scanning adjacency lists costs in total.
For and , the heap-operation contributions are therefore
and the overall bound is
A uniform bound including larger arity and tiny graphs is . Arity greater than the number of vertices offers no useful extra heap levels. These bounds assume adjacency lists; with an adjacency matrix, scanning neighbours contributes instead. No rebuilding of the heap is required after each decrease.
With an adjacency list, initialization and the outer loop cost . Each vertex is visited once, and the adjacency scans inspect each edge of a graph twice, once from each endpoint. The total worst-case time is therefore , with labels and recursion-stack space. An adjacency matrix representation instead incurs scanning time.
1. Run depth-first search over all vertices of , recording their finish order.
2. Construct the graph transpose by reversing every edge.
3. Mark every vertex unvisited again. In decreasing first-pass finish order, start a transpose search whenever the next vertex is unvisited. The vertices newly reached by each search form one strongly connected component.
The finish order prevents a second-pass search from entering a different still-unassigned component, while mutual reachability makes it visit the entire current component. With adjacency lists, each traversal and the transposition scan takes time. Thus the total worst-case time is , including isolated vertices.
An infinite trace exists exactly when a directed cycle is reachable from , by the infinite walk criterion in a finite directed graph. Compute the reachable set with depth-first search, compute its strongly connected components, and return true if any component has at least two vertices or contains a self-loop. A singleton without a self-loop does not qualify.
If the test succeeds, follow a path from to the cycle and traverse the cycle forever. Conversely, an infinite trace in a finite graph repeats a vertex, producing a reachable nonempty closed walk and hence a directed cycle. Reachability, component construction and the self-loop check all scan adjacency lists only a constant number of times. The worst-case time is , with auxiliary space for a straightforward transpose-based implementation.
Use minimum-hop shortest paths by minimizing the lexicographic order pair : total weight first, number of edges second. Extend a pair across an edge of weight by adding , and compare the full pair in both the priority queue and relaxation:
for v in V: key[v] = (infinity,infinity)
key[s] = (0,0)
Q = indexed min-priority-queue containing all vertices, keyed by key
while Q is not empty:
    u = extract-min(Q)
    if key[u].distance == infinity: break
    for each edge (u,v) of weight w with v still in Q:
        candidate = (key[u].distance + w, key[u].hops + 1)
        if candidate <lex key[v]:
            key[v] = candidate
            decrease-key(Q,v,candidate)
for v in V: best[v] = key[v].hops
All weights are positive, so extending a path strictly increases its first component. The usual Dijkstra's algorithm settled-label proof therefore applies to these ordered pairs: no path through a not-yet-settled vertex can later improve an extracted minimum. Among equal minimum weights, the secondary component selects the fewest edges. Merely breaking extraction ties by vertex name would not implement this objective.
With a binary heap and adjacency lists, the bound is , with extra storage. Unreachable vertices have best = infinity. In the paper's example, the resulting pairs in order are , so the requested edge counts are .
Maintain white, gray and black colors for undiscovered, active and completed vertices. A single traversal clock records DFS discovery and finishing times:
for v in V: color[v] = white; parent[v] = none
time = 0
visit(u):
    time = time+1; d[u] = time; color[u] = gray
    for v in adjacency[u]:
        if color[v] == white:
            parent[v] = u
            visit(v)
    color[u] = black; time = time+1; f[u] = time
for u in V:
    if color[u] == white: visit(u)
The outer loop makes a depth-first search forest even when the directed graph is disconnected. Each vertex is entered once and each directed adjacency entry is inspected once. Thus an adjacency list representation gives time and auxiliary storage, including the worst-case recursive stack. Sorting neighbors to impose a particular visit order would be additional work.
In depth-first search, mark every vertex white initially. At a white start vertex , increment a global clock, record and color it gray. Scan its outgoing adjacency list; recursively visit each still-white neighbor, recording the discovery edge. After all neighbors have been processed, color black, increment the clock and record . Start again from every remaining white vertex to obtain a forest. Each vertex is discovered once and each edge scanned once, so the time is with adjacency lists.
The DFS parenthesis property says that for distinct vertices , their intervals and are disjoint or one lies strictly inside the other. Moreover is a proper descendant in a rooted tree of exactly when . A recursive call finishes before its caller returns, while completed calls from separate branches have disjoint intervals; these two possibilities prove the property.
First run breadth-first search from to compute each distance . All are finite by hypothesis. Next compute the strongly connected components and their condensation graph . For every component , initialize a representative minimizing over . Process components in reverse topological order, using
Break equal-distance ties consistently, for example by fixed vertex index. Return for every .
Every vertex of one strongly connected component reaches every other; every reachable different component is reached through some first outgoing edge of . Since is a Directed acyclic graph, reverse topological order has already solved every successor. Induction over that order proves that the representative minimizes over all reachable vertices. This is minimum reachable label propagation.
All stages take time and space with explicit adjacency lists. Retaining parallel component edges is harmless: they can be scanned once each without sorting or deduplication. Reachability here includes the length-zero path, so ; this standard convention also makes the requested answer meaningful at a sink.