#!/usr/bin/env python3 # @EXPECTED_RESULTS@: TIME_LIMIT_EXCEEDED, WRONG_ANSWER """ Orient each edges multiedge or leave it unoriented, with the same probability (3 cases). Find all connected components in corresponding graph (no component contains a vertex with indegree > 0; connectivity is defined by the unoriented edges.) Then assemble the components weighted by the outdegree of the vertices and the unoriented edges. Pr(correct) >= 3^t. """ import random import math from collections import Counter random.seed(0) def root(w, parent): while w != parent[w]: # parent[w] = parent[parent[w]] # don't path compress, components are tiny w = parent[w] return w def main(): n, m, k = map(int, input().split()) edges = [] for _ in range(m): edges.append(tuple(map(int, input().split()))) # vertices are 1..n p = 0.0001 # change min to max in next line to get more correctness, worse time for _ in range(min(1000, int(math.log(p) / math.log(1 - 3 ** (-k))))): undirected_edge = {} # count multiplicity infected = [None] + [False] * n d_out = [None] + [0] * n coinflip = {} for e in edges: if e not in coinflip: coinflip[e] = random.choice([0,1,2]) if coinflip[e] == 0: if e in undirected_edge: undirected_edge[e] += 1 else: undirected_edge[e] = 1 else: if coinflip[e] == 1: u, v = e else: v, u = e d_out[u] += 1 infected[v] = True size = [None] + [d_out[u] for u in range(1, n + 1)] parent = [None] + list(range(1, n + 1)) # parent[0] ignored for u, v in undirected_edge: ru, rv = root(u, parent), root(v, parent) if infected[u] or infected[v]: infected[rv] = infected[ru] = True if ru == rv: size[ru] += 1 continue # weighted union by implicit vertex size (i.e., outedges do contribute) # This is probably overkill, the component size are always tiny if size[ru] > size[rv]: ru, rv = rv, ru size[rv] += size[ru] + undirected_edge[u, v] parent[ru] = rv component_sizes = Counter( size[u] for u in range(1, n + 1) if not infected[u] and parent[u] == u ) # If k becomes larger than k, do this programmatically: partitions = { 1: [{1: 1}], 2: [{2: 1}, {1: 2}], 3: [{3: 1}, {1: 3}, {1: 1, 2: 1}], 4: [{4: 1}, {1: 4}, {3: 1, 1: 1}, {1: 2, 2: 1}, {2: 2}], 5: [{5: 1}, {1: 5}, {4: 1, 1: 1}, {3: 1, 1: 2}, {3: 1, 2: 1}, {2: 2, 1: 1}], 6: [ {6: 1}, {1: 6}, {2: 3}, {2: 2, 1: 2}, {5: 1, 1: 1}, {3: 1, 1: 3}, {3: 1, 2: 1, 1: 1}, {3: 2}, {4: 1, 1: 2}, {4: 1, 2: 1}, ], }[k] for d in partitions: for i, sz in d.items(): if component_sizes[i] < sz: break else: components_to_report = set() for u in range(1, n + 1): if ( parent[u] == u and not infected[u] and size[u] in d and d[size[u]] > 0 ): components_to_report.add(u) d[size[u]] -= 1 cover = [ u for u in range(1, n + 1) if root(u, parent) in components_to_report ] print(len(cover)) print(*cover) return print("impossible") main()