Programming Assignment 2 - Graph Path Compression

Advanced Programming II, Fall 2003


Due Date

This assignment is due by 2:00 p.m. on Thursday, 16 October.

See the assignment turn-in page (last modified on 3 November 2003) for instructions on turning in your assignment.

Background

A graph is a set of nodes and a set of edges between nodes. Each node in a graph has a label unique among all nodes in the graph; a node is identified with its label. An edge of the graph is an ordered pair of (not necessarily distinct) node. The first node in the pair is called the tail node and the second node in the pair is called the head node; the edge is called an out edge relative to the tail node and a in edge relative to the head node.

Every graph has a source node and a sink node. A source node is a node with no in edges; a sink node is a node with no out edges. In the example above, node a is the source node and node d is the sink node.

For example, the graph

has nodes a, b, c, d, e, f, and g ; node a is the source node and node d is the sink node.

A path through a graph is a sequence of i nodes n0, n1, ... ni from the graph with the following properties:

  1. Node n0 is the source node.

  2. Nodes nk and nk + 1 for 0 <= k < i are connected by an edge.

  3. Node ni is the sink node.

For example, the node sequence

a, b, c, e, g, b, d

is a path through the graph given above, while the node sequence

a, b, c, e, g, b

is not a path for the graph above because it doesn't end at the sink node, and the node sequence

a, b, c, e, g, d

is not a path for the graph above because there is no edge between nodes g and d.

A path normally contains many redundant nodes. For example, because every path starts at the source node and ends at the sink node, it isn't really necessary to include them in the path.

A compressed path is formed by deleting redundant nodes from a path. A compressed path has the advantage of being shorter than the path from which it came, but it still has all the information necessary to reconstruct the complete path.

For example, the path

a, b, c, e, g, b, d

can be compressed by removing the source and sink nodes:

b, c, e, g, b

Notice that a compressed path usually won't be a path by the definition given above; however it's always possible to recover the proper path from the compressed path.

A minimal compressed path is a compressed path with no redundant nodes. For example, the path

a, b, c, e, g, b, d

produces the minimal compressed path

e

Note that, in general, minimal compressed paths need not be unique. For example, the path a, b, c through the graph

can be represented by any of the minimally compressed paths a, b, or c.

The Problem

Write a program that inputs from std-in a graph and one or more paths and outputs to std-out compressed versions of the input paths. The compressed paths output by your program should be minimal.

Input

The input consists of a graph, followed by one or more blank lines, followed by zero or more paths. Zero or more blank lines may appear between successive paths.

A graph is a sequence of one or more node descriptions. Each node description is a line containing one or more node labels; adjacent node labels are separated by one or more space characters. The first (leftmost) node label is a tail node; the remaining node labels are head nodes directly connected to the tail node. Each node description follows the next with no intervening blank lines.

A path description is a sequence of node labels from the given graph; each node label is separated from the next by one or more space characters. Each line contains a single path description, and a path description is contained in a single line.

Output

Output should be a sequence of compressed path descriptions in the same format as input. The path descriptions should be output in the same order they were input. A minimal compressed path may not be unique; if your program finds more than one minimal compressed path, it should output any one of them.

If the intput graph is incorrect, your program should output a descriptive error message end exit. If an input path description is incorrect, your program should write a descriptive error message to std-out; the error message should start with the characers "! " (that's bang followed by space).


This page last modified on 13 October 2003.