/*************************************************************************
 *  Kompilacja:  javac FlowNetwork.java
 *  Wykonanie:    java FlowNetwork V E
 *  Zależności: Bag.java FlowEdge.java
 *
 *  Sieć przepływowa z pojemnościami krawędzi, zaimplementowana za pomocą 
 *  list sąsiedztwa.
 *
 *************************************************************************/

public class FlowNetwork {
    private final int V;
    private int E;
    private Bag<FlowEdge>[] adj;
    
    // Pusty graf o V wierzchołkach
    public FlowNetwork(int V) {
        this.V = V;
        this.E = 0;
        adj = (Bag<FlowEdge>[]) new Bag[V];
        for (int v = 0; v < V; v++)
            adj[v] = new Bag<FlowEdge>();
    }

    // Losowy graf o V wierzchołkach i E krawędziach
    public FlowNetwork(int V, int E) {
        this(V);
        for (int i = 0; i < E; i++) {
            int v = StdRandom.uniform(V);
            int w = StdRandom.uniform(V);
            double capacity = StdRandom.uniform(100);
            addEdge(new FlowEdge(v, w, capacity));
        }
    }

    // Graf wczytywany ze strumienia wejściowego
    public FlowNetwork(In in) {
        this(in.readInt());
        int E = in.readInt();
        for (int i = 0; i < E; i++) {
            int v = in.readInt();
            int w = in.readInt();
            double capacity = in.readDouble();
            addEdge(new FlowEdge(v, w, capacity));
        }
    }

    // Liczba wierzchołków i krawędzi
    public int V() { return V; }
    public int E() { return E; }

    // Dodawanie krawędzi e na listach sąsiedztwa wierzchołków v i w
    public void addEdge(FlowEdge e) {
        E++;
        int v = e.from();
        int w = e.to();
        adj[v].add(e);
        adj[w].add(e);
    }

    // Zwracanie listy krawędzi incydentnych do v
    public Iterable<FlowEdge> adj(int v) {
        return adj[v];
    }

    // Zwracanie listy wszystkich krawędzi
    public Iterable<FlowEdge> edges() {
        Bag<FlowEdge> list = new Bag<FlowEdge>();
        for (int v = 0; v < V; v++)
            for (FlowEdge e : adj(v))
                list.add(e);
        return list;
    }

    // Łańcuch znaków reprezentujący graf - metoda działa w czasie kwadratowym
    public String toString() {
        String NEWLINE = System.getProperty("line.separator");
        StringBuilder s = new StringBuilder();
        s.append(V + " " + E + NEWLINE);
        for (int v = 0; v < V; v++) {
            s.append(v + ":  ");
            for (FlowEdge e : adj[v]) {
                s.append(e + "  ");
            }
            s.append(NEWLINE);
        }
        return s.toString();
    }

    // Klient testowy
    public static void main(String[] args) {
        int V = Integer.parseInt(args[0]);
        int E = Integer.parseInt(args[1]);
        FlowNetwork G = new FlowNetwork(V, E);

        StdOut.println(G);
    }
}
