Problem:
Traveling Salesman Problem

For a given weighted directed graph G(V, E), find the distance of the shortest route that meets the following criteria:

It is a closed cycle where it ends at the same point it starts.

It visits each vertex exactly once.

Input

|V| |E|
s0 t0 d0
s1 t1 d1
:
s|E|-1 t|E|-1 d|E|-1

|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.

si and ti represent source and target vertices of i-th edge (directed) and di represents the distance between si and ti (the i-th edge).

Output

Print the shortest distance in a line. If there is no solution, print -1.

Constraints

2 ≤ |V| ≤ 15

0 ≤ di ≤ 1,000

There are no multiedge

Sample Input 1

4 6
0 1 2
1 2 3
1 3 9
2 0 1
2 3 6
3 2 4

Sample Output 1

16

Sample Input 2

3 3
0 1 1
1 2 1
0 2 1

Sample Output 2

-1

Solution in JAVA (judge verdict: Accepted)


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.util.Arrays;
import java.util.StringTokenizer;

class Main{
	public static void main(String[] args) {
		SC sc=new SC(System.in);
		int V=sc.nextInt();	//Vertex->頂点数
		int E=sc.nextInt();//Edge->辺の数
		int[][] rinsetu=new int[V][V];
		int INF=1000000007;
		int[][] bitDP=new int[1<<V][V];
		//最初だからねしょうがないね
		//巡回セールスマン問題は、最初の地点は決まっておらず、任意の頂点からスタートできるので、
		//かならずしもスタートを頂点0からできないのでは？と思うが、それは偽で、
		//巡回セールスマン問題でもとめる最短経路は閉路（サイクル）なので、そのサイクルを構成する任意の点から始めても、
		//同じ答えを出すことができるので、スタートを頂点0だと決め打ちしても問題ない。
		for (int i = 0; i < V; i++) {
			Arrays.fill(rinsetu[i], INF);
		}
		for(int i=0; i<(1<<V); i++) {
			for(int j=0; j<V; j++) {
				bitDP[i][j]=INF;
			}
		}
		for(int i=0; i<E; i++) {
			int from=sc.nextInt();
			int to=sc.nextInt();
			int cost=sc.nextInt();
			rinsetu[from][to]=cost;
		}
		bitDP[1][0]=0;
		for(int i=0; i<(1<<V); i++) {
			for(int j=0; j<V; j++) {
				if(bitDP[i][j]==INF) {
					continue;		//経路を確立していないなら
				}
				else {
					for(int k=0; k<V; k++) {
						if((1&i>>k)==1) {
							continue;
						}
						else if(rinsetu[j][k]==INF){
							continue;
						}
						else {
							int nexti=i|(1<<k);
							bitDP[nexti][k]=Math.min(bitDP[nexti][k], bitDP[i][j]+rinsetu[j][k]);
						}
					}
				}
			}
		}
		int all=(1<<V)-1;
		int min=INF;
		for(int i=0; i<V; i++) {
			if(bitDP[all][i]==INF) {
				continue;
			}
			else if(rinsetu[i][0]==INF) {//さいしょにもどれないとき
				continue;
			}
			else {
				int allcost=bitDP[all][i]+rinsetu[i][0];
				min=Math.min(min, allcost);
			}
		}
		if(min==INF) {
			pl(-1);
		}
		else {
			pl(min);
		}
	}
	public static void pl(Object o) {
		System.out.println(o);
	}
	public static void pl() {
		System.out.println();
	}
	public static void p(Object o) {
		System.out.print(o);
	}
	static class SC {
		private BufferedReader reader = null;
		private StringTokenizer tokenizer = null;
		public SC(InputStream in) {
			reader = new BufferedReader(new InputStreamReader(in));
		}
		public String next() {
			if (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					throw new UncheckedIOException(e);
				}
			}
			return tokenizer.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() {
			try {
				return reader.readLine();
			} catch (IOException e) {
				throw new UncheckedIOException(e);
			}
		}
	}
}