Problem:
サージェント・ライアン

「ライアン軍曹を救え」という指令のもと、アイヅ軍の救出部隊はドイツリーの水上都市で敵軍と激しい戦闘を繰り広げていました。彼らは無事に軍曹と合流しましたが、敵の戦車が多く、救出ヘリを呼べずにいました。そこで、彼らは敵の戦車を混乱させるため、都市にある橋を全て爆破するという作戦を実行することにしました。

作戦はすぐに司令部に伝えられ、救出ヘリの準備が進められました。救出ヘリを飛ばすためには、いつ橋が全て爆破されるかを予測しなければなりません。軍のプログラマであるあなたの任務は、救出部隊が全ての橋の爆破に必要な時間を計算することです。

水上都市は N 個の島で構成されており、島と島との間には橋がかかっています。すべての島はツリー状に繋がっています(下図参照) 。ある島からある島への経路は、一通りだけ存在します。各橋を渡るには、橋ごとに決められた時間がかかり、どちらの方向にもその時間で橋を渡ることが可能です。

救出部隊はボートなど水上を移動する手段を持っていないので島と島の間を移動するには橋を通る他ありません。救出部隊は、その時いる島に隣接している橋のうち、必要なものを一瞬で爆破することができます。救出部隊が全ての橋を爆破するのに必要な最小の時間はいくらでしょうか。ただし、島の中での移動時間は考えません。

島の数、それぞれの橋情報を入力とし、橋を全て爆破するのに必要な最小の時間を出力するプログラムを作成してください。島はそれぞれ 1 から N の番号で表されます。橋は N-1 本あります。橋情報は、その橋が隣接している二つの島の番号(a, b)と、その橋を渡るのに必要な時間 t で構成されます。救出部隊は島番号 1 の島からスタートするものとします。

Input

複数のデータセットの並びが入力として与えられる。入力の終わりはゼロひとつの行で示される。各データセットは以下の形式で与えられる。

N
a1 b1 t1
a2 b2 t2
:
aN-1 bN-1 tN-1

入力はすべて整数で与えられる。1 行目に島の数 N (2 ≤ N ≤ 20) が与えられる。

続く N-1 行に i 番目の橋の情報が与えられる。 ai, bi, ti (1 ≤ ti ≤ 500) は、i 番目の橋を通って島 ai と島 bi の間を時間 ti で移動できることを表す。

データセットの数は 100 を超えない。

Output

データセットごとに、橋を全て爆破するのに必要な最小の時間を1行に出力する。

Sample Input

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

Output for the Sample Input

12

Solution in PHP (judge verdict: Accepted)

<?php
 
$file_handle = fopen('php://stdin', "r"); //fopen()は同位フォルダにファイルがあればその名前のみでOK
//$file_handle = fopen('aoj0235_in.txt', "r");
 
//dfs（再帰ver）(根から葉の親までの距離総計を$leafに格納していく)
function dfs($cur) {
    //グローバル変数定義
    global $dist;
    global $leaf;
    global $flag;
     
    //終了条件不要
    
    //現在の島を探索済みにする
    $flag[$cur['node']] = 1;
     
    $childnode = childnode($cur['node']);
    if (empty( $childnode )) return;
    foreach ($childnode as $island_num => $distance) {
    	if ( $flag[$island_num] === 1 ) continue;
        $grandchildnode = childnode($island_num);
        if (!empty($grandchildnode)) {
            $new['node'] = $island_num;
            $new['dist'] = $cur['dist'] + $dist[$cur['node']][$new['node']];
            dfs($new);
        } else {
            $leaf[$cur['node']] = $cur['dist'];     //ここが葉の親ならば
            $dist[$cur['node']][$island_num] = 0;   //バグの修正。孫ノードが存在しない橋への距離を０に。
            $dist[$island_num][$cur['node']] = 0;   //バグの修正。孫ノードが存在しない橋への距離を０に。
        }
    }
}
 
//子ノード抽出
function childnode($island){
    global $dist;
    global $flag;
   //未探索のみ子ノードとして取り出す
   $childnode = array();
   if (!empty($dist[$island])){
       foreach ($dist[$island] as $key => $val){
           if ($flag[$key] !== 1) {
               $childnode[$key] = $val;
           }
       }
   }
   return $childnode;
}
 
//最も根から葉の親までの距離が大きいものを取り出す
function max_dist($leaf){
    $max = 0;
    foreach ($leaf as $key => $val){
        if ($max < $leaf[$key]){
            $max = $leaf[$key];
        }
    }
    return $max;
}
 
function calc(){
    global $dist;
    global $leaf;
    global $max_dist;
    //まずは葉の親までの全部の橋のコストを合計して2倍。もともとダブルカウントなので全部足し算すればOK
    $sum = 0;
    foreach($dist as $key => $val){
        foreach($dist[$key] as $d2){
            $sum += $d2;
        }
    }
     
    //$sum から、根から葉の親までの距離が最も大きいものをマイナス
    $sum -= $max_dist;
    return $sum;
}
 
while (1){
    //変数の初期化
    $dist = array();
    $leaf = array();    //$leaf[葉の親のnum] = 根からの距離
    $flag = array();	//探索済みかどうか
 
    //ファイル読み込み
    $stdin = fscanf($file_handle, '%d');    //fscanf()で読み込んだものは配列として格納される
    $n = $stdin[0];
    //終了条件
    if ($n == 0){
        break;
    }
     
    for ($i=0; $i < $n-1; $i++){
        $info = fscanf($file_handle, '%d %d %d');
        $parent = $info[0]; $child = $info[1]; $distance = $info[2];
        $dist[$parent][$child] = $distance;
        $dist[$child][$parent] = $distance;
    }
    
    for ($i=1; $i<=$n; $i++){
    	$flag[$i] = 0;	//すべての島を未探索に。
    }
    
 
    //探索
    $stack['node'] = 1;     //スタートを$stackに入れて開始
    $stack['parent'] = NULL;
    $stack['dist'] = 0;
    dfs($stack);
    $max_dist = max_dist($leaf);
    $sum = calc();
    
    //出力
    echo $sum;
    echo PHP_EOL;
}
 
fclose($file_handle);