const max_i := ipower(26, 3); fn str2i(b : bytes) : int [ var r := 0; for i := 0 to len(b) do r := r * 26 + b[i] - 'a'; return r; ] record node [ qmap : int; visited : bool; parent : int; ] fn flood_fill(nodes : array(node, [max_i]), st : int, en : int, n_paths : int) : (bool, int) [ for pth := 0 to n_paths do [ for i := 0 to max_i do [ nodes[i].visited := false; nodes[i].parent := -1; ] var queue := [ st ]; while len_greater_than(queue, 0) do [ var q := queue[0]; if q = en then goto found_path; queue := queue[1 .. ]; if nodes[q].visited then continue; nodes[q].visited := true; var edges := nodes[q].qmap; while edges <> 0 do [ var e := bsr edges; edges btr= e; if nodes[e].visited then continue; queue +<= e; nodes[e].parent := q; ] ] var num_filled := 0; for i := 0 to max_i do [ if nodes[i].visited then num_filled += 1; ] return false, num_filled; found_path: var p := en; while true do [ var pp := nodes[p].parent; if pp = -1 then break; nodes[p].qmap btr= pp; nodes[pp].qmap btr= p; p := pp; ] ] return true, 0; ] fn try_remove(nodes : array(node, [max_i])) : int [ var candidates := empty(tuple2(int, int)); for n := 0 to max_i do [ var edges := nodes[n].qmap; while edges <> 0 do [ var e := bsr edges; edges btr= e; if e <= n then continue; var nn := nodes; nn[e].qmap btr= n; nn[n].qmap btr= e; var ff, num_filled := flood_fill~spark(nn, n, e, 3); candidates += select~lazy(ff, [ mktuple2(n, e) ], empty(tuple2(int, int))); ] ] for i := 0 to 0 bts len(candidates) do [ if popcnt i <> 3 then continue; var nn := nodes; var nn1 := -1; var nn2 := -1; var ii := i; while ii <> 0 do [ var c := bsr ii; ii btr= c; var n1 := candidates[c].v1; var n2 := candidates[c].v2; nn[n1].qmap btr= n2; nn[n2].qmap btr= n1; nn1 := n1; nn2 := n2; ] var ff, num_filled := flood_fill(nn, nn1, nn2, 1); if ff then continue; return num_filled; ] abort; ] fn main [ var lines := list_break_to_lines(read_lazy(h[0])); var nodes := array_fill(node.[ qmap : 0, visited : false, parent : -1, ], [max_i]); for line in lines do [ var x1 := str2i(line[ .. 3]); var c := map(list_break(line[5 .. ], ' '), str2i); for x2 in c do [ nodes[x1].qmap bts= x2; nodes[x2].qmap bts= x1; ] ] var num_vertices := 0; for i := 0 to max_i do if nodes[i].qmap <> 0 then num_vertices += 1; var s := try_remove(nodes); write(h[1], ntos(s * (num_vertices - s)) + nl); ]