Cod sursa(job #3227382)

Utilizator preda.andreiPreda Andrei preda.andrei Data 30 aprilie 2024 00:32:49
Problema Party Scor 0
Compilator java Status done
Runda Arhiva de probleme Marime 6 kb
/*
 * TODO
 *
 * Complexity: O(V + E), where V is the number of vertices
 *                             E is the number of edges.
 */

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
import java.util.StringTokenizer;

public class Scandal {
    public static void main(final String[] args) throws IOException {
        try (var std = new InOut("party.in", "party.out")) {
            var vars = std.in.nextInt();
            var conds = std.in.nextInt();

            var graph = new Graph(vars);
            for (var i = 0; i < conds; i += 1) {
                var a = std.in.nextInt();
                var b = std.in.nextInt();
                var type = std.in.nextInt();
                if (type == 0) {
                    graph.imply(-a, b);
                } else if (type == 1) {
                    graph.imply(-a, -b);
                } else if (type == 2) {
                    graph.imply(-b, -a);
                } else if (type == 3) {
                    graph.imply(a, -b);
                }
            }

            var res = solve(graph);
            std.out.println(res.size());
            for (var index : res) {
                std.out.println(index);
            }
        }
    }

    private static class Node {
        public Set<Integer> edges = new HashSet<>();
        public int low = -1;
        public int time = -1;
        public boolean inStack = false;

        public Boolean assignment = null;
    }

    private static class Graph {
        private Node[] nodes;

        public Graph(int vars) {
            this.nodes = new Node[2 * vars];
            for (var i = 0; i < nodes.length; i += 1) {
                this.nodes[i] = new Node();
            }
        }

        public int vars() {
            return this.nodes.length / 2;
        }

        public Node get(int vari) {
            return this.nodes[this.realIndex(vari)];
        }

        public void imply(int varA, int varB) {
            this.nodes[this.realIndex(varA)].edges.add(varB);
            this.nodes[this.realIndex(-varB)].edges.add(-varA);
        }

        private int realIndex(int vari) {
            return vari > 0 ? (vari - 1) : (nodes.length + vari);
        }
    }

    private static ArrayList<Integer> solve(Graph graph) {
        for (var vari : findOrder(graph)) {
            if (graph.get(vari).assignment == null) {
                graph.get(vari).assignment = false;
                graph.get(-vari).assignment = true;
            }
        }

        var res = new ArrayList<Integer>();
        for (var i = 1; i <= graph.vars(); i += 1) {
            if (graph.get(i).assignment == true) {
                res.add(i);
            }
        }
        return res;
    }

    private static ArrayList<Integer> findOrder(Graph graph) {
        var order = new ArrayList<Integer>();
        for (var i = 1; i <= graph.vars(); i += 1) {
            for (var v : new int[] { i, -i }) {
                if (graph.get(v).time == -1) {
                    tarjan(graph, v, new Stack<Integer>(), order);
                }
            }
        }
        Collections.reverse(order);
        return order;
    }

    private static int globalTime = 0;

    private static void tarjan(Graph graph, int node, Stack<Integer> st, ArrayList<Integer> order) {
        graph.get(node).time = graph.get(node).low = (globalTime += 1);

        st.push(node);
        graph.get(node).inStack = true;

        for (var other : graph.get(node).edges) {
            if (graph.get(other).time == -1) {
                tarjan(graph, other, st, order);
                graph.get(node).low = Math.min(graph.get(node).low, graph.get(other).low);
            }
            if (graph.get(other).inStack) {
                graph.get(node).low = Math.min(graph.get(node).low, graph.get(other).time);
            }
        }

        // Extract the strongly-connected component.
        if (graph.get(node).low >= graph.get(node).time) {
            while (order.isEmpty() || order.get(order.size() - 1) != node) {
                var top = st.pop();
                graph.get(top).inStack = false;
                order.add(top);
            }
        }
    }

    private static class InOut implements AutoCloseable {
        public MyScanner in;
        public PrintStream out;

        /** Constructor for using standard IO. */
        public InOut() {
            in = new MyScanner(new InputStreamReader(System.in));
            out = System.out;
        }

        /** Constructor for using file IO. */
        public InOut(String pathIn, String pathOut) throws IOException {
            in = new MyScanner(new FileReader(pathIn));
            out = new PrintStream(pathOut);
        }

        @Override
        public void close() {
        }
    }

    private static class MyScanner {
        private BufferedReader br;
        private StringTokenizer st;

        public MyScanner(Reader reader) {
            br = new BufferedReader(reader);
        }

        public String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    return "";
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}