Problem:
Minimum-Cost Arborescence

Find the sum of the weights of edges of the Minimum-Cost Arborescence with the root r for a given weighted directed graph G = (V, E).

Input

|V| |E| r
s0 t0 w0
s1 t1 w1
:
s|E|-1 t|E|-1 w|E|-1

, where |V| is the number of vertices and |E| is the number of edges in the graph. The graph vertices are named with the numbers 0, 1,..., |V|-1 respectively. r is the root of the Minimum-Cost Arborescence.

si and ti represent source and target verticess of i-th directed edge. wi represents the weight of the i-th directed edge.

Output

Print the sum of the weights the Minimum-Cost Arborescence.

Constraints

1 ≤ |V| ≤ 100

0 ≤ |E| ≤ 1,000

0 ≤ wi ≤ 10,000

G has arborescence(s) with the root r

Sample Input 1

4 6 0
0 1 3
0 2 2
2 0 1
2 3 1
3 0 1
3 1 5

Sample Output 1

6

Sample Input 2

6 10 0
0 2 7
0 1 1
0 3 5
1 4 9
2 1 6
1 3 2
3 4 3
4 2 2
2 5 8
3 5 3

Sample Output 2

11

Solution in JAVA (judge verdict: Runtime Error)

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Map.Entry;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

import javax.swing.text.Segment;

public class Main {

	public static long Chu_Liu_Edmonds(final int V, int root, ArrayList<HashMap<Integer, Long>> rev_adj) {
		// ??????????????\???????°???????????????????????±???????
		long[] min_costs = new long[V];
		int[] min_pars = new int[V];
		min_costs[root] = 0;
		min_pars[root] = root;
		//System.out.println(rev_adj);

		for (int start = 0; start < V; start++) {
			if (start == root) { continue; }
			long min_cost = -1;
			int min_par = -1;

			for (final Entry<Integer, Long> entry : rev_adj.get(start).entrySet()) {
				final int par = entry.getKey();
				final long cost = entry.getValue();

				if (min_cost < 0 || min_cost > cost) {
					min_par = par;
					min_cost = cost;
				}
			}

			min_pars[start] = min_par;
			min_costs[start] = min_cost;
		}

		// ??????????????¨??????
		int next_nodes = 0;
		int[] belongs = new int[V];
		boolean[] is_cycle = new boolean[V];
		Arrays.fill(belongs, V);
		
		for (int start = 0; start < V; start++) {
			boolean[] used = new boolean[V];
			
			int curr = start;
			while (!used[curr] && min_pars[curr] != curr) {
				used[curr] = true;
				curr = min_pars[curr];
			}
			
			// ??????????????\?????????
			if (curr != root) {
				if(belongs[curr] >= V){
					belongs[curr] = next_nodes;
					is_cycle[curr] = true;
					
					int cycle_start = curr;
					while (min_pars[curr] != cycle_start) {
						belongs[min_pars[curr]] = next_nodes;
						is_cycle[min_pars[curr]] = true;
						curr = min_pars[curr];
					}
					
					next_nodes++;
				}
			}else{
				// ????????¨??¢?????????
				belongs[curr] = next_nodes;
				next_nodes++;
			}
		}
		
		if(next_nodes == V){ return Arrays.stream(min_costs).sum(); }
		
		
		long cycle_sum = 0;
		for(int i = 0; i < V; i++){
			if(!is_cycle[i]){ continue; }
			cycle_sum += min_costs[i];
		}
		
		ArrayList<HashMap<Integer, Long>> next_rev_adj = new ArrayList<HashMap<Integer, Long>>();
		for(int i = 0; i < next_nodes; i++){
			next_rev_adj.add(new HashMap<Integer, Long>());
		}
		for(int start = 0; start < V; start++){
			final int start_belongs = belongs[start];
			for(final Entry<Integer, Long> entry : rev_adj.get(start).entrySet()){
				final int prev = entry.getKey();
				final int prev_belongs = belongs[prev];
				
				if(start_belongs == prev_belongs){ continue; }
				else if(is_cycle[start]){
					next_rev_adj.get(start_belongs).put(prev_belongs, rev_adj.get(start).get(prev) - min_costs[start]);
				}else{
					next_rev_adj.get(start_belongs).put(prev_belongs, rev_adj.get(start).get(prev));
				}
			}
		}
		
		//System.out.println(cycle_sum);
		return cycle_sum + Chu_Liu_Edmonds(next_nodes, root, next_rev_adj);
	}

	public static void main(String[] args) throws IOException {
		try (Scanner sc = new Scanner(System.in)) {
			final int V = sc.nextInt();
			final int E = sc.nextInt();
			final int S = sc.nextInt();

			ArrayList<HashMap<Integer, Long>> fwd_adj = new ArrayList<HashMap<Integer, Long>>();
			ArrayList<HashMap<Integer, Long>> rev_adj = new ArrayList<HashMap<Integer, Long>>();
			for (int i = 0; i < V; i++) {
				fwd_adj.add(new HashMap<Integer, Long>());
			}
			for (int i = 0; i < V; i++) {
				rev_adj.add(new HashMap<Integer, Long>());
			}

			for (int i = 0; i < E; i++) {
				final int s = sc.nextInt();
				final int t = sc.nextInt();
				final long w = sc.nextLong();

				if (!fwd_adj.get(s).containsKey(t)) {
					fwd_adj.get(s).put(t, w);
				} else {
					fwd_adj.get(s).put(t, Math.min(w, fwd_adj.get(s).get(t)));
				}

				if (!rev_adj.get(t).containsKey(s)) {
					rev_adj.get(t).put(s, w);
				} else {
					rev_adj.get(t).put(s, Math.min(w, rev_adj.get(t).get(s)));
				}
			}

			System.out.println(Chu_Liu_Edmonds(V, S, rev_adj));
		}
	}

	public static class Scanner implements Closeable {
		private BufferedReader br;
		private StringTokenizer tok;

		public Scanner(InputStream is) throws IOException {
			br = new BufferedReader(new InputStreamReader(is));
		}

		private void getLine() throws IOException {
			while (!hasNext()) {
				tok = new StringTokenizer(br.readLine());
			}
		}

		private boolean hasNext() {
			return tok != null && tok.hasMoreTokens();
		}

		public String next() throws IOException {
			getLine();
			return tok.nextToken();
		}

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

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

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

		public int[] nextIntArray(int n) throws IOException {
			final int[] ret = new int[n];
			for (int i = 0; i < n; i++) {
				ret[i] = this.nextInt();
			}
			return ret;
		}

		public long[] nextLongArray(int n) throws IOException {
			final long[] ret = new long[n];
			for (int i = 0; i < n; i++) {
				ret[i] = this.nextLong();
			}
			return ret;
		}

		public void close() throws IOException {
			br.close();
		}
	}
}