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.util.Arrays;
import java.util.Scanner;
public class Main
{
	public static void main(String[] args) 
	{
		Scanner in=new Scanner(System.in);
		while(in.hasNext())
		{
			int n=in.nextInt();
			int m=in.nextInt();
			int M=1000000;
			int road[][]=new int[n+1][n+1];
			for(int i=0;i<=n;i++)
				Arrays.fill(road[i], M);
			for(int i=0;i<=n;i++)
				road[i][i]=0;
			for(int i=0;i<m;i++)
			{
				String s[]=in.next().split(",");
				road[Integer.valueOf(s[0])][Integer.valueOf(s[1])]=Integer.valueOf(s[2]);
				road[Integer.valueOf(s[1])][Integer.valueOf(s[0])]=Integer.valueOf(s[3]);
			}
			String va[]=in.next().split(",");
			int s=Integer.valueOf(va[0]);
			int t=Integer.valueOf(va[1]);
			int give=Integer.valueOf(va[2]);
			int cost=Integer.valueOf(va[3]);
			int ans=give-cost;
			int start=0;
			int goal=0;
			for(int I=0;I<2;I++)
			{
				int p=0;
				int leng[]=new int[n+1];// minimum distance
				int v[] = new int[n+1];// decision flag
				if(I==0)
				{
					start =s;
					goal=t;
				}
				else
				{
					start=t;
					goal=s;
				}
				for(int k=0;k<=n;k++)
				{
					leng[k]=M;
					v[k]=0;
				}
				leng[start]=0;
				for(int i=0;i<=n;i++)
				{
					int min=M;//最小の節点を探す
					for(int k=0;k<=n;k++)
					{
						if(v[k]==0&&leng[k]<min)
						{
							p=k;
							min=leng[k];
						}
					}
					v[p]=1;//確定フラグ
					for(int k=0;k<=n;k++) //pを経由してkに至長さがそれまでの最短経路より小さければ更新
					{
						if((leng[p]+road[p][k])<leng[k])
							leng[k]=leng[p]+road[p][k];
					}
				}
				ans-=leng[goal];
			}
			System.out.println(ans);
		}
	}
}