TAKMIČENJA IZ PROGRAMIRANJA


Sva pitanja, predloge ili primedbe u vezi sa takmičenjima iz programiranja možete slati na e-mail:

tak.prog@gmail.com

U toku perioda za žalbe, sve žalbe možete slati na ovaj isti e-mail.

Mars.java    4,124 b      izvorni kod rešenja
mars.checker.pas    469 b      program za testiranje
mars.tests.rar    977,810 b      test primeri

zadatak: Mars

Pošto je istraživanje Marsa sve popularnije, nacionalna svemirska agencija SCG Space Agency je pre određenog vremena poslala sopstvene robote, kojih ima n, na Mars. Ovi roboti se kreću po površini Marsa, skupljaju uzorke kamenja i slično, i šalju podatke nazad na Zemlju. Međutim, pošto koriste zastareli hardver, neki od robota su se već pokvarili. SCG Space Agency ne može direktno da sazna koji su roboti u kvaru, jer oni i dalje šalju nazad podatke. Jedini način da se to sazna je da se nekom robotu pošalje zahtev da izvrši inspekciju nekog drugog robota. Ali, problem je što robot koji vrši inspekciju takođe može da bude u kvaru - u tom slučaju rezultat inspekcije nije validan. Preciznije, ako robot A vrši inspekciju robota B, onda je rezultat inspekcije dat u tabeli.

     A      B      Rezultat inspekcije
ispravan ispravan B je ispravan
ispravan neispravan B je neispravan
neispravan ispravan rezultat je slučajan
neispravan neispravan rezultat je slučajan

Pošto je urađeno m različitih inspekcija, SCG Space Agency želi da sazna spisak svih robota za koje se sigurno može tvrditi da su neispravni, kako bi pokrenula proceduru njihovog samouništenja.

Ulaz:

U prvom redu ulaznog fajla mars.in nalaze se brojevi n i m (n ≤ 1000, m ≤ 10^5). U svakom od sledećih m redova nalaze se podaci o jednoj inspekciji. To su redom brojevi A, B i R. A je indeks robota koji vrši inspekciju, dok je B indeks robota nad kojim se vrši inspekcija. Roboti su numerisani brojevima od 1 do n. R je rezultat inspekcije - 0 označava da je robot B ispravan, a 1 da je neispravan.

Izlaz:

U prvi red izlaznog fajla mars.out treba ispisati broj robota za koje se sa sigurnošću tvrdi da su neispravni. U drugom redu treba da se nalazi spisak tih robota, sortiran po indeksu robota.

Primer:

mars.in      mars.out
5 6
1 2 0
2 3 0
3 1 1
5 1 0
1 4 1
5 4 0
        
2
1 5

Objašnjenje:

Ako pretpostavimo da je robot 1 ispravan, sledi da su i roboti 2 i 3 ispravni, na osnovu prve i druge inspekcije. Ali zbog treće inspekcije imamo kontradikciju, pa sledi da je robot 1 sigurno neispravan. Zbog toga i četvrte inspekcije robot 5 je takođe sigurno neispravan. O ostalim robotima ne možemo ništa da zaključimo.

fajl: Mars.java
import java.io.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class Mars {

    static BufferedInputStream in;
    static StreamTokenizer tok;
    static PrintStream out;

    static int nextInt() throws Exception {
        tok.nextToken();
        return (int) tok.nval;
    }

    public static final int RUNNING = 0;
    public static final int BROKEN = 1;

    static class Edge {
        int v;
        int result;
        public Edge(int v, int result) {
            this.v = v;
            this.result = result;
        }
    }

    int n;
    List[] edges;
    boolean[][] conn0;
    boolean[][] conn1;

    void readInput() throws Exception {
        n = nextInt();

        edges = new List[n];
        for (int i = 0; i < n; i++) {
            edges[i] = new ArrayList();
        }
        conn0 = new boolean[n][n];
        conn1 = new boolean[n][n];

        int m = nextInt();
        for (int i = 0; i < m; i++) {
            int u = nextInt() - 1;
            int v = nextInt() - 1;
            int result = nextInt();

            if (result == 0) {
                if (conn0[u][v])
                    throw new Exception();
                conn0[u][v] = true;
                edges[u].add(new Edge(v, result));
            } else if (!conn1[u][v]) {
                conn1[u][v] = true;
                conn1[v][u] = true;
                edges[u].add(new Edge(v, result));
                edges[v].add(new Edge(u, result));
            }
        }
    }

    boolean[] broken;

    boolean[] visited;
    int[] mark;
    int[] queue;

    boolean bfs(int source) {
        Arrays.fill(visited, false);
        int head = 0, tail = 0;

        queue[0] = source;
        mark[source] = RUNNING;
        visited[source] = true;

        while (head <= tail) {
            int u = queue[head++];

            for (Edge e : (List<Edge>) edges[u]) {
                if (broken[e.v] && e.result == RUNNING)
                    return true;

                if (visited[e.v]) {
                    if (mark[e.v] == RUNNING && e.result == BROKEN)
                        return true;
                    if (mark[e.v] == BROKEN && e.result == RUNNING)
                        return true;
                } else {
                    mark[e.v] = e.result;
                    if (e.result == RUNNING) {
                        visited[e.v] = true;
                        queue[++tail] = e.v;
                    }
                }
            }
        }
        return false;
    }

    List brokenList = new ArrayList();

    void solve() {
        broken = new boolean[n];

        visited = new boolean[n];
        mark = new int[n];
        queue = new int[n];

        for (int source = 0; source < n; source++)
            if (!broken[source])
                if (bfs(source)) {
                    broken[source] = true;
                    brokenList.add(source);
                }

        Collections.sort(brokenList);
    }

    void printOutput() {
        out.println(brokenList.size());
        for (int i : (List<Integer>) brokenList)
            out.print((i+1) + " ");
        out.println();
    }

    public static int DEFAULT_TEST_INDEX = 1;

    public static void main(String[] args) throws Exception {
//        int testIndex = args.length > 0 ? Integer.parseInt(args[0]) : DEFAULT_TEST_INDEX;
//        String inpath = String.format("mars.%02d.in", testIndex);
//        String outpath = String.format("mars.%02d.1.out", testIndex);
//
//        in = new BufferedInputStream(new FileInputStream(inpath));
//        out = new PrintStream(new BufferedOutputStream(new FileOutputStream(outpath)));
//        tok = new StreamTokenizer(in);

        in = new BufferedInputStream(System.in);
        out = System.out;

        Mars m = new Mars();
        m.readInput();
        m.solve();
        m.printOutput();

//        in.close();
//        out.close();
    }
}