PQ Tree
A PQ tree is a tree-based data structure that represents a set of permutations over a group of elements. It was discovered and named by Kellogg S. Booth and George S. Lueker in 1976 to solve the following problem:
Given \(m\) sets \(S_i\), find a permutation of \(1\sim n\) such that all elements within each set are consecutive.
A PQ tree can be constructed in \(O(n+\sum|S_i|)\) time. The construction method introduced in this article has a time complexity of \(O(nm)\).
Definition
A PQ tree has three types of nodes: leaf nodes, P-nodes, and Q-nodes. Leaf nodes represent elements in the permutation. A P-node indicates that its children can be arranged in any order, while a Q-node indicates that the order of its children can be reversed. All non-leaf nodes are either P-nodes or Q-nodes. A P-node has at least 2 children, and a Q-node has at least 3 children.
Due to the node definitions, the PQ tree itself represents all valid solutions, and its preorder traversal yields one of them.
The following figure shows a PQ tree.

Its preorder traversal 1,2,3,4,5 represents a valid solution. If the children of the P-node are rearranged to 4,2,3, we obtain another valid solution 1,4,2,3,5. Keeping the order of the P-node's children unchanged and reversing the order of the Q-node's children yields another valid solution 5,3,2,4,1.
Construction
PQ trees use the child–sibling representation.
We construct a PQ tree incrementally.
First, build a tree with a P-node as the root and \(n\) children, namely \(1,2,\ldots,n\), representing the PQ tree with no constraints. As constraints are added one by one, we continuously modify this tree.
When adding a new constraint set \(S\), we mark all leaf nodes belonging to this set as black, and leaf nodes not in this set as white. For all non-leaf nodes, if all their children are black, mark them as black; if all their children are white, mark them as white; otherwise, mark them as gray. In the diagrams below, black, white, and gray nodes are represented by black, gray, and half-black-half-gray colors, respectively.
We require that nodes in the PQ tree be sorted by color.
Bottom-Up Method
The smallest subtree containing all black nodes is called the pertinent subtree, and its root (not necessarily the root of the entire tree) is called the pertinent root.
The process of adding a constraint is called a reduction. A reduction consists of two phases: the bubble phase and the reduce phase.
Bubble Phase
The bubble phase only processes the pertinent subtree. We mark all nodes in the pertinent subtree as black or gray and compute the number of pertinent children for each node. To do this efficiently, we process the pertinent subtree from leaves to the root. This requires recording the parent of each node, but during the reduce phase, a node's parent often needs to be modified. To construct in linear time, only the children of P-nodes and the last child of a Q-node always have their correct parent recorded. For other children of a Q-node, their parent is updated during the bubble phase using the parent of the last child.
When encountering an intermediate node, we check whether its sibling already has a valid parent. If not, mark it as blocked. If its sibling later obtains a valid parent, update this node's parent and remove the mark. If at the end of the bubble phase, there is still a contiguous block of blocked nodes (as in case Q3 below), a "pseudo-node" without a parent becomes the parent of that block and is removed during the reduce phase.
Reduce Phase
The reduce phase processes nodes using a queue. First, enqueue all leaf nodes within the constraint. Each time, dequeue the front node \(u\) and process it. If \(u\)'s parent is also in the pertinent subtree, enqueue \(\mathit{fa}_u\).
For each node \(u\), we discuss cases. If it does not belong to any of these cases, there is no solution.
Leaf Node
Mark \(u\) as black.
P-Node
If all children are black, mark \(u\) as black.


If \(u\) has both black and white children, and \(u\) is the pertinent root, create a new P-node \(v\) as the root of all its black children.


If \(u\) has both black and white children, and \(u\) is not the pertinent root, perform the following operations:
- Create a new P-node \(f\) as the root of all black children.
- Create a new P-node \(e\) as the root of all white children.
- If \(e\) (and/or \(f\)) has only one child, do not create a new node; instead, assign \(e\) (and/or \(f\)) directly to that child.
- Change \(u\) to a Q-node, set its children as \(e\) and \(f\), and mark it as gray.
Note that according to the earlier definition, a Q-node has at least 3 children, so \(u\) here is treated as a "pseudo-node" and will be processed further later.


If \(u\) has a gray child \(p\), and \(u\) is the pertinent root, create a new P-node \(v\) as the root of all its black children, set \(v\)'s sibling as the last black child of \(p\), and then set \(v\) as the last child of \(p\).


If \(u\) has a gray child \(p\), and \(u\) is not the pertinent root, perform the following operations:
- Create a new P-node \(f\) as the root of all black children.
- Create a new P-node \(e\) as the root of all white children.
- If \(e\) (and/or \(f\)) has only one child, do not create a new node; instead, assign \(e\) (and/or \(f\)) directly to that child.
- Set \(e\)'s sibling as the last white child of \(p\), and then set \(e\) as the last child of \(p\).
- Set \(f\)'s sibling as the last black child of \(p\), and then set \(f\) as the last child of \(p\).


If \(u\) has exactly two gray children \(p_1,p_2\), perform the following operations:
- Create a new P-node \(f\) as the root of all black children.
- If \(f\) has only one child, do not create a new node; instead, assign \(f\) directly to that child.
- Set the sibling of the last black child of \(p_1\) as \(f\).
- Set the sibling of \(f\) as the last black child of \(p_2\).
- Set the last child of \(p_2\) as the last white child of \(p_2\).
It can be seen that \(p_2\) is thus merged into \(p_1\).


Q-Node
If \(u\) has only black children, mark \(u\) as black. (The shape in the diagram below is incorrect.)


If \(u\) has a gray child \(p\), and all children with the same mark appear consecutively, perform the following operations:
- Let \(p_f\) be the last black child of \(p\), \(p_e\) be the last white child of \(p\), \(f\) be the black sibling of \(p\), and \(e\) be the white sibling of \(p\).
- Set the sibling of \(f\) as \(p_f\), and the sibling of \(e\) as \(p_e\).
- If \(p\) does not have a white sibling or a black sibling, set the last child of \(u\) as the last child of \(p\).
- Delete \(p\).


If \(u\) has exactly two gray children \(p_1,p_2\), and all children with the same mark appear consecutively, perform the above operation on both \(p_1\) and \(p_2\).


This construction method is from the original paper but is relatively inconvenient to implement.
Top-Down Method
Most implementations in OI currently use this method. The approach is similar, and the cases below can mostly be found above.
Note that according to the earlier coloring process, all black and white nodes already satisfy the conditions, so we only need to process gray nodes.
P-Node
- If \(u\) has more than two gray children, there is no solution.
- If \(u\) has only one gray child and no black children, recursively process the gray child.
- Otherwise, first clear \(u\)'s children, then add all white children. Create a new Q-node \(q_1\) and make it a child of \(u\). Add all gray children to \(q_1\). Create a new P-node \(p\) as the root of all black children, and insert \(p\) into the middle of \(q_1\). (This corresponds to all cases of P-nodes in the bottom-up method.)
Note that we require the two gray nodes to have all whites on the left and all blacks on the right (or vice versa), so we need to implement a split function split that can split the subtree's nodes into white and black parts while preserving all possibilities of the resulting subtrees' nodes.
Q-Node
- Find the leftmost and rightmost non-white node positions \(l,r\). If there are non-black nodes within \([l+1,r-1]\), there is no solution.
- If there are no black nodes and only one gray node, recursively process this gray node; otherwise, only need to split the nodes at positions \(l\) and \(r\).
Split Function
Let the node to split be \(u\). We want to split \(u\) into a forest where the left side is all white and the right side is all black. If \(u\) is not a gray node, directly return the subtree. Only consider the case where \(u\) is a gray node.
If \(u\) is a P-node:
- If \(u\) has at least two gray children, there is no solution.
- Otherwise, the left side consists of all white children, the middle is the recursively processed gray child, and the right side consists of all black children. Note that to preserve all possibilities, we need to create two new P-nodes as the roots of the white and black children, respectively. (Corresponds to case P4 in the bottom-up method.)
- Delete \(u\).
If \(u\) is a Q-node:
- If neither the forward nor reverse order satisfies white–gray–black, there is no solution.
- If there are at least two gray children, there is also no solution.
- Otherwise, recursively split the gray child.
- Delete \(u\).
Finally, delete all redundant nodes (nodes with only one child).
Code Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | |
Exercises
References
- Booth, Kellogg S. & Lueker, George S. (1976)."Testing for the consecutive ones property, interval graphs, and graph planarity using PQ-tree algorithms".Journal of Computer and System Sciences.13(3): 335–379.doi:10.1016/S0022-0000(76)80045-1.
- PQ Tree Algorithm and Consecutive Ones Problem
- CF243E Matrix PQTree - RainAir's Blog
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用