Problem:
Chinese Postman Problem

For a given weighted undirected 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.

The route must go through every edge at least once.

Input

|V| |E|
s0 t0 d0
s1 t1 d1
:
s|E|-1 t|E|-1 d|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.

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

Note that there can be multiple edges between a pair of vertices.

Output

Print the shortest distance in a line.

Constraints

2 ≤ |V| ≤ 15

0 ≤ |E| ≤ 1,000

0 ≤ di ≤ 1,000

si ≠ ti

The graph is connected

Sample Input 1

4 4
0 1 1
0 2 2
1 3 3
2 3 4

Sample Output 1

10

Sample Input 2

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

Sample Output 2

18

Sample Input 3

2 3
0 1 1
0 1 2
0 1 3

Sample Output 3

7

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Collections;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using static System.Math;
using System.Numerics;
static class Program{
	const int mod=(int)1e9+7;
	static bool[] ba;
	static int[] h,z;
	static int[][] dp;
	static List<int> li;
	static int x,o=int.MaxValue;
	static void Main(){
		Sc sc=new Sc();
		int[] s=sc.Ia;
		int n=s[0],m=s[1],ans=0;
		h=new int[n];
		var inf=int.MaxValue>>1;
		dp=new int[n][];
		for(int i=0;i<n;i++){
			dp[i]=new int[n];
			for(int j=0;j<n;j++){
				if(i!=j){dp[i][j]=inf;}
			}
		}
		for(int i=0;i<m;i++){
			int[] e=sc.Ia;
			dp[e[0]][e[1]]=Min(e[2],dp[e[0]][e[1]]);
			dp[e[1]][e[0]]=Min(e[2],dp[e[1]][e[0]]);
			h[e[0]]++;
			h[e[1]]++;
			ans+=e[2];
		}
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				for(int k=0;k<n;k++){dp[j][k]=Min(dp[j][k],dp[j][i]+dp[i][k]);}
			}
		}
		li=new List<int>();
		for(int i=0;i<n;i++){
			if(h[i]%2==1){li.Add(i);}
		}
		x=(1<<li.Count)-1;
		ba=new bool[x+1];
		z=new int[x+1];
		Fu(0,0,0);
		Console.WriteLine("{0}",ans+(o!=int.MaxValue?o:0));
	}
	static int Fu(int n,int b,int g){
		if(ba[b]){o=Min(o,g+z[b]);return z[b];}
		b|=1<<n;
		int p=n+1,u=int.MaxValue;
		while(((1<<p)&b)!=0){p++;}
		for(int i = li.Count-1;i>n;i--) {
			if((b&(1<<i))==0){
				if((b|(1<<i))!=x){
					b|=1<<i;
					while(((1<<p)&b)!=0){p++;}
					u=Min(u,Fu(p,b,g+dp[li[n]][li[i]])+dp[li[n]][li[i]]);
					b^=1<<i;
				}
				else{
					o=Min(o,g+dp[li[n]][li[i]]);
					u=dp[li[n]][li[i]];
					break;
				}
			}
		}
		b^=1<<n;
		ba[b]=true;
		z[b]=u;
		return u;
	}
}

public class Sc{
	public int I{get{return int.Parse(Console.ReadLine());}}
	public long L{get{return long.Parse(Console.ReadLine());}}
	public double D{get{return double.Parse(Console.ReadLine());}}
	public string S{get{return Console.ReadLine();}}
	public int[] Ia{get{return Array.ConvertAll(Console.ReadLine().Split(),int.Parse);}}
	public long[] La{get{return Array.ConvertAll(Console.ReadLine().Split(),long.Parse);}}
	public double[] Da{get{return Array.ConvertAll(Console.ReadLine().Split(),double.Parse);}}
	public string[] Sa{get{return Console.ReadLine().Split();}}
	public object[] Oa{get{return Console.ReadLine().Split();}}
	public int[] Ia2{get{return Array.ConvertAll(("0 "+Console.ReadLine()+" 0").Split(),int.Parse);}}
	public int[] Ia3(int a){return Array.ConvertAll((a.ToString()+" "+Console.ReadLine()).Split(),int.Parse);}
	public int[] Ia3(bool a,int b,bool c,int d){return Array.ConvertAll(((a?b.ToString()+" ":"")+Console.ReadLine()+(c?" "+d.ToString():"")).Split(),int.Parse);}
	public long[] La2{get{return Array.ConvertAll(("0 "+Console.ReadLine()+" 0").Split(),long.Parse);}}
	public long[] La3(int a){return Array.ConvertAll((a.ToString()+" "+Console.ReadLine()).Split(),long.Parse);}
	public long[] La3(bool a,int b,bool c,int d){return Array.ConvertAll(((a?b.ToString()+" ":"")+Console.ReadLine()+(c?" "+d.ToString():"")).Split(),long.Parse);}
	public T[] Arr<T>(int n,Func<T> f){var a=new T[n];for(int i=0;i<n;i++){a[i]=f();}return a;}
	public T[] Arr<T>(int n,Func<int,T> f){var a=new T[n];for(int i=0;i<n;i++){a[i]=f(i);}return a;}
	public T[] Arr<T>(int n,Func<string[],T> f){var a=new T[n];for(int i=0;i<n;i++){a[i]=f(Console.ReadLine().Split());}return a;}
	public T[] Arr<T>(int n,Func<int,string[],T> f){var a=new T[n];for(int i=0;i<n;i++){a[i]=f(i,Console.ReadLine().Split());}return a;}
}