388 lines
11 KiB
Rust
388 lines
11 KiB
Rust
#[derive(Debug)]
|
|
struct Vertex {
|
|
name: u16,
|
|
edges: Vec<u16>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Graph {
|
|
index: Vec<u16>,
|
|
vertices: Vec<Vertex>,
|
|
stack: Vec<Vertex>,
|
|
}
|
|
|
|
impl Graph {
|
|
pub fn new(g: &crate::Graph) -> Self {
|
|
let mut vertices: Vec<_> = (0..g.num_vertices())
|
|
.map(|i| Vertex {
|
|
name: i,
|
|
edges: Vec::new(),
|
|
})
|
|
.collect();
|
|
|
|
for (start, s) in g.edge_list.iter().enumerate() {
|
|
vertices[start].edges.extend_from_slice(s);
|
|
}
|
|
|
|
Self {
|
|
index: (0..g.num_vertices()).collect(),
|
|
vertices,
|
|
stack: Vec::new(),
|
|
}
|
|
}
|
|
|
|
fn is_empty(&self) -> bool {
|
|
self.vertices.is_empty()
|
|
}
|
|
|
|
fn remove_vertex(&mut self, v: u16) -> &Vertex {
|
|
let i = self.index[v as usize];
|
|
// dbg!(&self.index, v, i);
|
|
let vertex = self.vertices.swap_remove(i as usize);
|
|
|
|
assert_eq!(vertex.name, v);
|
|
|
|
if (i as usize) < self.vertices.len() {
|
|
self.index[self.vertices[i as usize].name as usize] = i;
|
|
}
|
|
|
|
for &e in &vertex.edges {
|
|
let i = self.index[e as usize];
|
|
let p = self.vertices[i as usize]
|
|
.edges
|
|
.iter()
|
|
.position(|&o| o == v)
|
|
.unwrap();
|
|
self.vertices[i as usize].edges.swap_remove(p);
|
|
}
|
|
// dbg!(&self.index);
|
|
|
|
self.stack.push(vertex);
|
|
|
|
self.stack.last().unwrap()
|
|
}
|
|
|
|
fn reinsert_vertices(&mut self, n: usize) -> impl Iterator<Item = &Vertex> {
|
|
for _ in 0..n {
|
|
let v = self.stack.pop().unwrap();
|
|
for &e in &v.edges {
|
|
let i = self.index[e as usize];
|
|
self.vertices[i as usize].edges.push(v.name);
|
|
}
|
|
|
|
self.index[v.name as usize] = self.vertices.len() as u16;
|
|
self.vertices.push(v);
|
|
}
|
|
|
|
self.vertices[(self.vertices.len() - n)..].iter()
|
|
}
|
|
|
|
fn get_vertex_with_degree_greater(&self, min_degree: u16) -> Option<u16> {
|
|
self.vertices
|
|
.iter()
|
|
.find(|&v| v.edges.len() >= min_degree as usize)
|
|
.map(|v| v.name)
|
|
}
|
|
|
|
fn get_vertex_with_degree(&self, degree: u16) -> Option<u16> {
|
|
self.vertices
|
|
.iter()
|
|
.find(|&v| v.edges.len() == degree as usize)
|
|
.map(|v| v.name)
|
|
}
|
|
|
|
fn get_edges(&self, v: u16) -> impl Iterator<Item = u16> + '_ {
|
|
let i = self.index[v as usize];
|
|
self.vertices[i as usize].edges.iter().copied()
|
|
}
|
|
|
|
fn get_edge(&self, v: u16) -> Option<u16> {
|
|
self.get_edges(v).next()
|
|
}
|
|
|
|
fn get_degree(&self, v: u16) -> u16 {
|
|
let i = self.index[v as usize];
|
|
self.vertices[i as usize].edges.len() as u16
|
|
}
|
|
}
|
|
|
|
pub fn binary_vertex(graph: &mut Graph, k: u16) -> Option<Vec<u16>> {
|
|
let vertex = match graph.get_vertex_with_degree_greater(2) {
|
|
Some(vertex) => vertex,
|
|
None => {
|
|
return {
|
|
let mut c = 0;
|
|
while let Some(vertex) = graph.get_vertex_with_degree_greater(1) {
|
|
graph.remove_vertex(vertex);
|
|
c += 1;
|
|
}
|
|
|
|
if c <= k {
|
|
Some(
|
|
graph
|
|
.reinsert_vertices(c as usize)
|
|
.map(|v| v.name)
|
|
.collect(),
|
|
)
|
|
} else {
|
|
let _ = graph.reinsert_vertices(c as usize);
|
|
None
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
if k == 0 {
|
|
return None;
|
|
}
|
|
|
|
graph.remove_vertex(vertex);
|
|
|
|
match binary_vertex(graph, k - 1) {
|
|
Some(mut s) => {
|
|
s.push(vertex);
|
|
Some(s)
|
|
}
|
|
None => {
|
|
let _ = graph.reinsert_vertices(1);
|
|
let num_neighbors = graph.get_edges(vertex).count();
|
|
|
|
if num_neighbors <= k as usize {
|
|
let mut c = 0;
|
|
while let Some(e) = graph.get_edge(vertex) {
|
|
graph.remove_vertex(e);
|
|
c += 1;
|
|
}
|
|
let mut r = binary_vertex(graph, k - c);
|
|
if let Some(r) = &mut r {
|
|
r.extend(graph.reinsert_vertices(c as usize).map(|v| v.name));
|
|
} else {
|
|
let _ = graph.reinsert_vertices(c as usize);
|
|
}
|
|
r
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn reduction(graph: &mut Graph, k: u16) -> Option<Vec<u16>> {
|
|
if let Some(vertex) = graph.get_vertex_with_degree(0) {
|
|
graph.remove_vertex(vertex);
|
|
|
|
let r = reduction(graph, k);
|
|
|
|
let _ = graph.reinsert_vertices(1);
|
|
|
|
r
|
|
} else if k == 0 {
|
|
if graph.is_empty() {
|
|
Some(Vec::new())
|
|
} else {
|
|
None
|
|
}
|
|
} else if let Some(vertex) = graph.get_vertex_with_degree(1) {
|
|
let neighbor = graph.get_edge(vertex).unwrap();
|
|
|
|
graph.remove_vertex(neighbor);
|
|
let mut r = reduction(graph, k - 1);
|
|
|
|
let i = graph.reinsert_vertices(1);
|
|
|
|
if let Some(r) = &mut r {
|
|
r.extend(i.map(|v| v.name));
|
|
}
|
|
|
|
r
|
|
} else if let Some(vertex) = graph.get_vertex_with_degree_greater(2) {
|
|
graph.remove_vertex(vertex);
|
|
|
|
match reduction(graph, k - 1) {
|
|
Some(mut s) => {
|
|
let i = graph.reinsert_vertices(1);
|
|
s.extend(i.map(|v| v.name));
|
|
Some(s)
|
|
}
|
|
None => {
|
|
let _ = graph.reinsert_vertices(1);
|
|
let num_neighbors = graph.get_edges(vertex).count();
|
|
|
|
if num_neighbors <= k as usize {
|
|
let mut c = 0;
|
|
while let Some(e) = graph.get_edge(vertex) {
|
|
graph.remove_vertex(e);
|
|
c += 1;
|
|
}
|
|
let mut r = reduction(graph, k - c);
|
|
|
|
let i = graph.reinsert_vertices(c as usize);
|
|
if let Some(r) = &mut r {
|
|
r.extend(i.map(|v| v.name));
|
|
}
|
|
r
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
unreachable!()
|
|
}
|
|
}
|
|
|
|
pub fn reduction2(graph: &mut Graph, k: u16) -> Option<Vec<u16>> {
|
|
if let Some(vertex) = graph.get_vertex_with_degree(0) {
|
|
graph.remove_vertex(vertex);
|
|
|
|
let r = reduction2(graph, k);
|
|
|
|
let _ = graph.reinsert_vertices(1);
|
|
|
|
r
|
|
} else if graph.is_empty() {
|
|
Some(Vec::new())
|
|
} else if k == 0 {
|
|
if graph.is_empty() {
|
|
Some(Vec::new())
|
|
} else {
|
|
None
|
|
}
|
|
} else if let Some(vertex) = graph.get_vertex_with_degree(1) {
|
|
let neighbor = graph.get_edge(vertex).unwrap();
|
|
|
|
if k < 1 {
|
|
return None;
|
|
}
|
|
|
|
graph.remove_vertex(neighbor);
|
|
let mut r = reduction2(graph, k - 1);
|
|
|
|
let i = graph.reinsert_vertices(1);
|
|
if let Some(r) = &mut r {
|
|
r.extend(i.map(|v| v.name));
|
|
}
|
|
|
|
r
|
|
} else if let Some(vertex) = graph.get_vertex_with_degree(2) {
|
|
let (a, b) = {
|
|
let mut i = graph.get_edges(vertex);
|
|
(i.next().unwrap(), i.next().unwrap())
|
|
};
|
|
|
|
if graph.get_edges(a).any(|n| n == b) {
|
|
if k < 2 {
|
|
return None;
|
|
}
|
|
graph.remove_vertex(a);
|
|
graph.remove_vertex(b);
|
|
|
|
let mut r = reduction2(graph, k - 2);
|
|
|
|
let i = graph.reinsert_vertices(2);
|
|
if let Some(r) = &mut r {
|
|
r.extend(i.map(|v| v.name));
|
|
}
|
|
|
|
r
|
|
} else if graph.get_degree(a) == 2
|
|
&& graph.get_degree(b) == 2
|
|
&& graph.get_edges(a).find(|&v| v != vertex).unwrap()
|
|
== graph.get_edges(b).find(|&v| v != vertex).unwrap()
|
|
{
|
|
if k < 2 {
|
|
return None;
|
|
}
|
|
let w = graph.get_edges(a).find(|&v| v != vertex).unwrap();
|
|
|
|
graph.remove_vertex(vertex);
|
|
graph.remove_vertex(w);
|
|
|
|
let mut r = reduction2(graph, k - 2);
|
|
|
|
let i = graph.reinsert_vertices(2);
|
|
if let Some(r) = &mut r {
|
|
r.extend(i.map(|v| v.name));
|
|
}
|
|
|
|
r
|
|
} else {
|
|
if k < 2 {
|
|
return None;
|
|
}
|
|
graph.remove_vertex(a);
|
|
graph.remove_vertex(b);
|
|
|
|
match reduction2(graph, k - 2) {
|
|
Some(mut s) => {
|
|
let i = graph.reinsert_vertices(2);
|
|
s.extend(i.map(|v| v.name));
|
|
Some(s)
|
|
}
|
|
None => {
|
|
let _ = graph.reinsert_vertices(2);
|
|
|
|
let mut c = 0;
|
|
while let Some(e) = graph.get_edge(a) {
|
|
graph.remove_vertex(e);
|
|
c += 1;
|
|
}
|
|
while let Some(e) = graph.get_edge(b) {
|
|
graph.remove_vertex(e);
|
|
c += 1;
|
|
}
|
|
|
|
if c <= k {
|
|
let mut r = reduction2(graph, k - c);
|
|
|
|
let i = graph.reinsert_vertices(c as usize);
|
|
if let Some(r) = &mut r {
|
|
r.extend(i.map(|v| v.name));
|
|
}
|
|
r
|
|
} else {
|
|
let _ = graph.reinsert_vertices(c as usize);
|
|
None
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if let Some(vertex) = graph.get_vertex_with_degree_greater(3) {
|
|
if k < 1 {
|
|
return None;
|
|
}
|
|
|
|
graph.remove_vertex(vertex);
|
|
|
|
match reduction2(graph, k - 1) {
|
|
Some(mut s) => {
|
|
let i = graph.reinsert_vertices(1);
|
|
s.extend(i.map(|v| v.name));
|
|
Some(s)
|
|
}
|
|
None => {
|
|
let _ = graph.reinsert_vertices(1);
|
|
let num_neighbors = graph.get_edges(vertex).count();
|
|
|
|
if num_neighbors <= k as usize {
|
|
let mut c = 0;
|
|
while let Some(e) = graph.get_edge(vertex) {
|
|
graph.remove_vertex(e);
|
|
c += 1;
|
|
}
|
|
let mut r = reduction2(graph, k - c);
|
|
|
|
let i = graph.reinsert_vertices(c as usize);
|
|
if let Some(r) = &mut r {
|
|
r.extend(i.map(|v| v.name));
|
|
}
|
|
r
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
unreachable!("{k}")
|
|
}
|
|
}
|