Problem:
大工の褒美

ある日、殿様は一人の大工に、「台風や地震が来たときに町人が避難できる、頑丈で大きな建物を造りなさい。」と命じました。しかし、その頑丈で大きな建物を完成させるには、大きな太い柱が必要です。町にそんな大きな柱はありません。そこで、大工は遠くの山里まで大きな柱を調達しに行くことになりました（大工は町から里山に行って、町に戻ってくる必要があります）。

大工の褒美は、殿様から受け取ったお金から柱の代金と交通費を差し引いた余りです。下の地図のように、山里に行くには、いろいろな町を通るたくさんの街道があり、2つの町をつなぐ街道はそれぞれ交通費が違います。大工の褒美を最大にするにはどのように街道をたどり調達すればよいでしょうか。最大となる大工の褒美を出力するプログラムを作成してください。ただし、町の数を n とすれば、各町は 1 から n までの整数で識別されます。2 つの町を直接つなぐ街道は 2 本以上ありません。

※ 矢印上の数字は、その方向に行くための交通費を示します。

Input

入力は以下の形式で与えられます。

n
m
a1,b1,c1, d1
a2,b2,c2, d2
:
am,bm,cm, dm
s,g,V,P

1 行目に町の総数 n（ n ≤ 20）、2 行目に街道の総数 m (m ≤ 100) が与えられます。続く m 行に i 番目の街道の情報 ai, bi, ci, di (1 ≤ ai, bi ≤ n, 0 ≤ ci, di ≤ 1,000) が与えられます。ai, bi は街道 i がつないでいる町の番号、 ci は ai から bi への交通費、 di は bi から ai への交通費を表します。

最終行に大工が出発する町の番号 s、柱のある山里の番号 g、殿様から大工が受け取ったお金 V、柱の代金 P が与えられます。

Output

大工の褒美（整数）を１行に出力してください。

Sample Input

6
8
1,2,2,2
1,3,4,3
1,4,4,2
2,5,3,2
3,4,4,2
3,6,1,2
4,6,1,1
5,6,1,2
2,4,50,30

Output for the Sample Input

11

Solution in JAVA (judge verdict: Accepted)

import java.awt.geom.Point2D;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.*;

public class Main {	
	Scanner in = new Scanner(System.in);
	public static void main(String[] args){
		new Main();
	}
	public Main(){		
		new AOJ0117();
	}
	
	class AOJ0117{
		int cost[][]; //コスト
		int d[];//頂点sからの最短距離
		boolean used[];//素手に使用されたかのフラグ
		int V;//頂点数
		int INF;
		
		void dijkstra(int s){
			//list = new int[V];前の頂点を保存したいとき
			d = new int[V+1];
			used = new boolean[V+1];
			Arrays.fill(d,INF);
			Arrays.fill(used, false);
			d[s] = 0;
			while(true){
				int v=-1;
				for(int u=0;u<=V;u++){//まだ使われていない頂点のうち最小のものを探す
					if(!used[u]&&(v==-1||d[u]<d[v]))v=u;
				}
				if(v==-1)break;
				used[v]=true;
				for(int u=0;u<=V;u++){
					d[u] = Math.min(d[u],d[v]+cost[v][u]);
//					if(d[u]>d[v]+cost[v][u]){   前の頂点を保存したい時は更新された時に
//						d[u]=d[v]+cost[v][u];
//						list[u] = v;
//					}
				}
			}
		}
		
		
		public AOJ0117() {
			INF = Integer.MAX_VALUE/2;
			V = in.nextInt();
			int m = in.nextInt();
			cost = new int[V+1][V+1];//[from][to]
			for(int i=0;i<=V;i++)Arrays.fill(cost[i],Integer.MAX_VALUE/2);
			for(int i=0;i<m;i++){
				String input[] = in.next().split(",");
				cost[Integer.parseInt(input[0])][Integer.parseInt(input[1])] = Integer.parseInt(input[2]);
				cost[Integer.parseInt(input[1])][Integer.parseInt(input[0])] = Integer.parseInt(input[3]);
			}
			String input[] = in.next().split(",");
			int start = Integer.parseInt(input[0]),goal = Integer.parseInt(input[1]);
			int money = Integer.parseInt(input[2]),hasira = Integer.parseInt(input[3]);
			dijkstra(start);
			int result = d[goal];
			dijkstra(goal);
			result += d[start];
			System.out.println(money-(result+hasira));
		}
	}
	

	class AOJ2503{
		int MAX = 0;
		public AOJ2503() {
			Scanner in = new Scanner(System.in);
			int n = in.nextInt();
			int m = in.nextInt();

			int[][] cost = new int[n][n];

			int[] dp = new int[n];
			for(int i=0;i<n*n;i++){
				cost[i/n][i%n]=MAX;
			}
			for(int i=0;i<m;i++){
				int a = in.nextInt();
				int b = in.nextInt();
				cost[a][b]=in.nextInt();
			}	
			//			TODO 一番大きいパスを0のポイントからn-1のポイントまでの

			for(int s=1;s<n;s++){
				for(int i=0;i<=s;i++){
					if(cost[i][s]==MAX)continue;
					dp[s]=Math.max(dp[s],dp[i]+cost[i][s]);
				}
			}
			for(int s=0;s<n;s++)for(int i=0;i<n;i++){
				if(cost[s][i]==MAX)continue;
				dp[i]=Math.max(dp[s]+cost[s][i],dp[i]);
			}
			for(int i=0;i<n;i++)System.out.print(dp[i]+" ");
			System.out.println();
			System.out.println(dp[n-1]);
		}
	}
}