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

public class Main {
	static class Vertex {
		int number;
		int degree;
		Vertex neighbor[];
		Edge edge[];
		int cost;
		boolean mark;

		Vertex (int number, int n, int m) {
			this.number = number;
			this.degree = 0;
			neighbor = new Vertex[n];
			edge = new Edge[m];
			this.cost = Integer.MAX_VALUE;
			this.mark = false;
		}

		public void remake(Vertex v, Edge e) {
			neighbor[degree] = v;
			edge[degree] = e;
			this.degree++;
		}

		public String toString() {
			String s = "";
			for (int i = 0; i < degree; i++) {
				s += (neighbor[i].number + 1) + " ";
				if (edge[i].v1 == this) {
					s += edge[i].costFromV1 + " ";
				} else {
					s += edge[i].costFromV2 + " ";
				}
			}
			return s;
		}
	}

	static class Edge {
		int number;
		Vertex v1, v2;
		int costFromV1;
		int costFromV2;

		Edge (int number, Vertex v1, Vertex v2, int costFromV1, int costFromV2) {
			this.number = number;
			this.v1 = v1;
			this.v2 = v2;
			this.costFromV1 = costFromV1;
			this.costFromV2 = costFromV2;
		}
	}

	public static void main(String args[]) {
		Scanner sc = new Scanner(System.in);
		int n, m;
		Vertex vertex[];
		Edge edge[];

		n = sc.nextInt();
		m = sc.nextInt();
		vertex = new Vertex[n];
		edge = new Edge[m];
		for (int i = 0; i < n; i++) {
			vertex[i] = new Vertex(i, n, m);
		}
		for (int i = 0; i < m; i++) {
			String s[] = sc.next().split(",");
			int a = Integer.valueOf(s[0]) - 1;
			int b = Integer.valueOf(s[1]) - 1;
			int c = Integer.valueOf(s[2]);
			int d = Integer.valueOf(s[3]);
			edge[i] = new Edge(i, vertex[a], vertex[b], c, d);
			vertex[a].remake(vertex[b], edge[i]);
			vertex[b].remake(vertex[a], edge[i]);
		}
		String s[] = sc.next().split(",");
		int a = Integer.valueOf(s[0]) - 1;
		int b = Integer.valueOf(s[1]) - 1;
		int c = Integer.valueOf(s[2]);
		int d = Integer.valueOf(s[3]);
		int total = c;
		total -= minimumWay(vertex, edge, a, b);
		for (int i = 0; i < n; i++) {
			vertex[i].cost = Integer.MAX_VALUE;
			vertex[i].mark = false;
		}
		total -= d;
		total -= minimumWay(vertex, edge, b, a);
		System.out.println(total);
	}

	public static int minimumWay(Vertex v[], Edge e[], int start, int goal) {
		int n = v.length;
		int index = start;
		int minIndex;

		v[start].cost = 0;
		while (!v[goal].mark) {
			v[index].mark = true;
			for (int i = 0; i < v[index].degree; i++) {
				Vertex v1 = v[index].neighbor[i];
				Edge e1 = v[index].edge[i];
				if (!v1.mark) {
					if (e1.v1 == v[index]) {
						if (v[index].cost + e1.costFromV1 < v1.cost) {
							v1.cost = v[index].cost + e1.costFromV1;
						}
					} else {
						if (v[index].cost + e1.costFromV2 < v1.cost) {
							v1.cost = v[index].cost + e1.costFromV2;
						}
					}
				}
			}
			minIndex = -1;
			for (int i = 0; i < n; i++) {
				if (!v[i].mark && (minIndex == -1 || v[i].cost < v[minIndex].cost)) {
					minIndex = i;
				}
			}
			index = minIndex;
		}
		return v[goal].cost;
	}
}