#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<utility>
#include<queue>
using namespace std;

struct Node{
  //ノードの情報
  int num;//ノードの番号(あっても意味ない気はするが、一応)
  vector<pair<int,int>> edge;//各エッジの接続先のノード番号とコスト

  //ダイクストラ法用のデータ
  bool confirmed=false;
  int mincost=1000000000;//そのノードへの最小コスト
};

struct Node_comparision{
  bool operator()(const Node node1,const Node node2) const{
    return node1.mincost > node2.mincost;
  }
};

//添字は0にする
//vectorは参照渡しで基本はする(遅いので)
void dijkstra(vector<Node>& nodes,int r){
  //優先度の低いものを取りだす(popで)
  //取り出したものが接続するノードのmincostを取り出す
  //new演算子で新たに確保しないと、参照先を書き換えしてしまう
  Node* x= new Node;*x=nodes[r];
  priority_queue<Node,vector<Node>,Node_comparision> nodes_sub;nodes_sub.push(*x);
  while(nodes_sub.size()!=0){
    Node* y= new Node;*y=nodes_sub.top();
    while(nodes[y->num].confirmed==true){
      nodes_sub.pop();
      if(nodes_sub.size()==0) break;
      *y=nodes_sub.top();
    }
    if(nodes_sub.size()==0) break;
    nodes_sub.pop();
    nodes[y->num].confirmed=true;
    int l=y->edge.size();
    for(int i=0;i<l;i++){
      nodes[y->edge[i].first].mincost=min(nodes[y->edge[i].first].mincost,y->mincost+y->edge[i].second);
      Node* z= new Node;*z=nodes[y->edge[i].first];
      if(nodes[z->num].confirmed==false) nodes_sub.push(*z);
      delete z;
    }
    delete y;
  }
  delete x;
}

int main(){
  int n,m;cin >> n >> m;
  vector<Node> Nodes1(n);
  vector<Node> Nodes2(n);
  for(int i=0;i<n;i++){Nodes1[i].num=i;}
  for(int i=0;i<n;i++){Nodes2[i].num=i;}

  for(int i=0;i<m;i++){
    int a,b,c,d;scanf("%d,%d,%d,%d",&a,&b,&c,&d);
    Nodes1[a-1].edge.push_back(make_pair(b-1,c));
    Nodes1[b-1].edge.push_back(make_pair(a-1,d));
    Nodes2[a-1].edge.push_back(make_pair(b-1,c));
    Nodes2[b-1].edge.push_back(make_pair(a-1,d));
  }

  int s,g,v,p;scanf("%d,%d,%d,%d",&s,&g,&v,&p);
  Nodes1[s-1].mincost=0;Nodes2[g-1].mincost=0;

  dijkstra(Nodes1,s-1);
  dijkstra(Nodes2,g-1);

  cout << v-p-(Nodes1[g-1].mincost+Nodes2[s-1].mincost) << endl;
}

