#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<long long> VL;
typedef vector<vector<long long>> VVL;
typedef pair<ll,int> Pair;
typedef tuple<int,int,int> tpl;

#define ALL(a)  (a).begin(),(a).end()
#define SORT(c) sort((c).begin(),(c).end())
#define REVERSE(c) reverse((c).begin(),(c).end())
#define EXIST(m,v) (m).find((v)) != (m).end()
#define LB(a,x) lower_bound((a).begin(), (a).end(), x) - (a).begin()
#define UB(a,x) upper_bound((a).begin(), (a).end(), x) - (a).begin()

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define RFOR(i,a,b) for(int i=(a)-1;i>=(b);--i)
#define RREP(i,n) RFOR(i,n,0)

#define en "\n"

constexpr double EPS = 1e-9;
constexpr double PI  = 3.1415926535897932;
constexpr int INF = 2147483647;
constexpr long long LINF = 1LL<<60;
constexpr long long MOD = 1000000007; // 998244353;

template<class T> inline bool chmax(T& a, T b){if(a<b){a=b;return true;}return false;}
template<class T> inline bool chmin(T& a, T b){if(a>b){a=b;return true;}return false;}

struct Edge{
    int from, to, id=-1;
    ll cost=1, k;

    Edge(int from, int to, ll cost=1, ll k=1): from(from), to(to), cost(cost), k(k) {}
    Edge() {}

    friend istream &operator>>(istream  &input, Edge &e ){ 
        input >> e.from >> e.to >> e.cost >> e.k;
        e.from--; e.to--;
        return input;            
    }

    Edge rev(void){
        return Edge(to, from, cost, k);
    }
};

vector<vector<Edge>> edge;
vector<bool> vis;

void Main(){
    int N,M,X,Y; cin >> N >> M >> X >> Y; X--; Y--;
    edge.resize(N);
    REP(_,M){
        Edge e; cin >> e;
        edge[e.from].emplace_back(e);
        edge[e.to].emplace_back(e.rev());
    }

    VL d(N,LINF);
    priority_queue<Pair,vector<Pair>,greater<Pair>> q;
    q.emplace(0,X);
    while(!q.empty()){
        auto [cost, v] = q.top(); q.pop();
        if(!chmin(d[v], cost)) continue;

        for(auto& e : edge[v]){
            ll t = (cost+e.k-1)/e.k * e.k;
            q.emplace(t+e.cost, e.to);
        }
    }

    ll ans = d[Y];
    cout << (ans<LINF ? ans : -1) << en;
    return;
}

int main(void){
    cin.tie(0);cout.tie(0);ios_base::sync_with_stdio(0);cout<<fixed<<setprecision(15);
    int t=1; //cin>>t;
    REP(_,t) Main();
    return 0;
}
#include <bits/stdc++.h>
#define int long long int
#define ll long long int
#define ld long double
#define getFaster ios_base::sync_with_stdio(false), cin.tie(nullptr)
#define rep(i, init, n) for (int i = init; i < (int)n; i++)
#define rev(i, n, init) for (int i = (int)n; i >= init; i--)
#define MOD1 1e9 + 7
#define MOD2 998244353
#define f first
#define s second
#define endl '\n'
#define pii pair<int, int>
#define tii tuple<int, int>
#define all(v) v.begin(), v.end()
#define mt make_tuple
#define precise(i) cout << fixed << setprecision(i)
#define codejam cout << "Case #" << ii + 1 << ": ";
#define impossible cout << "IMPOSSIBLE" << endl;
#define error(s) throw runtime_error(s)
#define hash hash1
std::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
int myRand(int R)
{
     int val = rng() % R;
     assert(val >= 0);
     return val;
}

const long double PI = atan(1.0) * 4;
const int32_t INF32 = 2e9 + 7;
const int64_t INF64 = 3e18;
const int32_t LOG = 21;
int32_t MOD = MOD1;

using namespace std;

//-------------------DEBUGGING-------------------------
void my_debugger(string s, int LINE_NUM) { cerr << endl; }
template <typename start, typename... end>
void my_debugger(string s, int LINE_NUM, start x, end... y)
{
     if (s.back() != ',')
     {
          s += ',';
          cerr << "LINE(" << LINE_NUM << "): ";
     }
     int i = s.find(',');
     cerr << s.substr(0, i) << " = " << x;
     s = s.substr(i + 1);
     if (!s.empty())
          cerr << ", ";
     my_debugger(s, LINE_NUM, y...);
}

#ifdef AJIT
#define debug(...) my_debugger(#__VA_ARGS__, __LINE__, __VA_ARGS__);
#else
#define debug(...) ;
#endif

void setMod(int mod_val)
{
     MOD = mod_val;
}
//-----------------------------------------------------

void files_init()
{
     freopen("maxflow.in", "r", stdin);
     freopen("maxflow.out", "w", stdout);
}

const int N = 2e5 + 5;
const int LOGN = 20;

int from[N],to[N],cost[N];
vector<int> g[N];
vector<int> vals;
int pow2[65];
int ans=0;

int getOther(int i,int edgeNo)
{
     return from[edgeNo]^to[edgeNo]^i;
}


void dfs(int i,int prev=-1,int cur_xor=0)
{ 
     vals.push_back(cur_xor);   
     for(auto e:g[i])
     {
          if(e==prev)continue;
          int j=getOther(i,e);
          dfs(j,e,cur_xor^cost[e]);
     }
}

int32_t main()
{
     getFaster;
     //files_init();
     int tests = 1;
     //cin >> tests;
     rep(ii, 0, tests)
     {
          setMod(MOD1);
          pow2[0]=1;
          rep(i,1,62)
          {
               pow2[i]=pow2[i-1]*2;
               while(pow2[i]>=MOD)pow2[i]-=MOD;
          }
          int n;
          cin>>n;
          rep(i,1,n)
          {
               cin>>from[i]>>to[i]>>cost[i];
               g[from[i]].push_back(i);
               g[to[i]].push_back(i);
          }
          
          dfs(1);
          
          vector<int> cnt0(62),cnt1(62);
          rep(i,0,61)
          {
               for(auto it:vals)
               {
                    if((1LL<<i)&it)
                    cnt1[i]++;
                    else
                    cnt0[i]++;
               }
          }

          for(auto it:vals)
          {
               rev(i,60,0)
               {
                    if((1LL<<i)&it)
                    cnt1[i]--;
                    else
                    cnt0[i]--;
               }

               rev(i,60,0)
               {
                    if((1LL<<i)&it)
                    ans+=pow2[i]*cnt0[i];
                    else
                    ans+=pow2[i]*cnt1[i];
               }
               ans%=MOD;
          }

          cout<<ans<<endl;
     }
     return 0;
}