Problem:
Time is Money
The city of ICPC has made excessive pedestrian separation, making
    transportation in the city quite complicated.  Citizens of the ICPC
    city thus have big concern on efficient transportation to save
    time.
    The residents are eager to reach their destinations as fast as possible
    by repeating taxi rides on driveways and walks on footpaths.
Many cabstands are in the city.  Footpaths and/or driveways
    directly connect some of the cabstand pairs allowing both-way
    traffic.
    Some pairs of cabstands may have no direct nor indirect paths.
When you are on foot at a
    cabstand, you can either
Walk a footpath, if any, to another cabstand, or
Pick up a taxi, if any driveway connects the cabstand.
When you are on a taxi, you can either
Keep riding to another cabstand via a driveway, or
Get out of the taxi.
You can get out of a taxi only at cabstands.
Transportation on a footpath or a driveway takes time defined for
    each of the roads.  In addition, you have to wait one minute to
    pick up a taxi for the first time.  The waiting time is
    doubled for each subsequent taxi picks, that is, two minutes for
    the second time, four minutes for the third time, and
    2
99
minutes for the 100-th time.
You are initially at one of the cabstands on foot.
    Find the shortest time possible to reach the destination cabstand.
Input
The input consists of multiple datasets, each in the following format.
n
p
q
a
1
b
1
c
1
…
a
p
b
p
c
p
d
1
e
1
f
1
…
d
q
e
q
f
q
Here,
n
,
p
, and
q
are the numbers of cabstands,
  footpaths, and driveways, respectively.
n
is an integer between 2 and 20000, inclusive.
  Cabstands are numbered 1 through
n.
p
and
q
are positive integers not exceeding 20000.
a
i
,
b
i
, and
c
i
describe the
i-
th footpath, meaning that it connects the
  cabstands numbered
a
i
and
b
i
,
and it takes
c
i
minutes to walk.
d
j
,
e
j
, and
f
j
describe the
j-
th driveway, meaning that it connects the
  cabstands numbered
d
j
and
e
j
,
and it takes a ride of
f
j
minutes.
a
i
,
b
i
,
d
j
,
  and
e
j
are positive integers not
  exceeding
n.
c
i
and
f
j
are positive integers not exceeding 10
6
.
The end of the input is indicated by a line containing three zeros.
  The total of
n,
the total of
p,
and the total of
q
of all the datasets
  do not exceed 200000, respectively.
Output
For each dataset, output a single line containing the shortest time
  required in minutes for transporting from the cabstand number 1 to
  the cabstand number
n
modulo 10
9
+7.  If such
  transportation is impossible, output −1 instead.
Sample Input
5 4 2
1 2 1
2 3 100
3 4 1
4 5 100
2 3 10
4 5 10
4 1 1
1 2 100
2 3 100
4 3 3
1 2 10
2 3 1
3 4 10
2 1 2
3 2 2
4 3 2
0 0 0
Output for the Sample Input
25
-1
7

Submitted solutions:

code_snippet: #define _USE_MATH_DEFINES
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using H = pair<ll, ll>;
using P = pair<ll, H>;
using vi = vector<int>;
using vl = vector<ll>;
#define all(a) (a).begin(), (a).end()
#define fs first
#define sc second
#define xx first
#define yy second.first
#define zz second.second
#define Q(i, j, k) mkp((i), mkp((j), (k)))
#define rng(i, s, n) for(int i = (s) ; i < (n) ; i++)
#define rep(i, n) rng(i, 0, (n))
#define mkp make_pair
#define vec vector
#define pb emplace_back
#define siz(a) int((a).size())
#define crdcomp(b) sort(all((b))); (b).erase(unique(all((b))), (b).end())
#define getidx(b, i) (lower_bound(all((b)), (i))-(b).begin())
#define ssp(i, n) (i==(ll)(n)-1?"\n":" ")
#define ctoi(c) (int)((c)-'0')
#define itoc(c) (char)((c)+'0')
#define cyes printf("Yes\n")
#define cno printf("No\n")
#define cdf(n) for(int __quetimes=(n); __quetimes>0; __quetimes--)
#define gcj printf("Case #%lld: ", __quetimes+1)
#define readv(a, n) (a).resize((n), 0); rep(i, (n)) (a)[i]=read()
#define found(a, x) (a.find(x)!=a.end())
constexpr ll mod = (ll)1e9 + 7;
constexpr ll Mod = 998244353;
constexpr ld EPS = 1e-10;
constexpr ll inf = (ll)1e15;
constexpr int Inf = 1e9;
constexpr int dx[] = { -1, 1, 0, 0 }, dy[] = { 0, 0, -1, 1 };
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
template<class T = ll>T read() { T u, k = scanf("%lld", &u); return u; }
string reads() { string s; cin >> s; return s; }
bool ina(H t, int h, int w) { return 0 <= t.fs && t.fs < h && 0 <= t.sc && t.sc < w; }
bool ina(int t, int l, int r) { return l <= t && t < r; }
ll gcd(ll i, ll j) { return j ? gcd(j, i % j) : i; }
template<typename T>
void fin(T x) { cout << x << endl; exit(0); }
//--------------------------------------------------------------
struct st {
    int to;
    ll cst;
    bool type;
};
struct ps {
    int p, t;
    ll c;
    bool ride;
    bool operator<(const ps& a) const {
        if ((t <= 40) != (a.t <= 40)) (t <= 40) < (a.t <= 40);
        if (t > 40 && a.t > 40) return t < a.t;
        return c < a.c;
    }
    bool operator>(const ps& a) const {
        if ((t <= 40) != (a.t <= 40)) (t <= 40) > (a.t <= 40);
        if (t > 40 && a.t > 40) return t > a.t;
        return c > a.c;
    }
};
signed main() {
    int n, p, q;
    while (cin >> n >> p >> q && n) {
        vec<vec<st>>e(n);
        rep(i, p) {
            int a, b, c;cin >> a >> b >> c;
            a--;b--;
            e[a].pb(st{ b,c,false });
            e[b].pb(st{ a,c,false });
        }
        rep(i, q) {
            int a, b, c;cin >> a >> b >> c;
            a--;b--;
            e[a].pb(st{ b,c,true });
            e[b].pb(st{ a,c,true });
        }
        ll pow[50];
        pow[0] = 1;
        rep(i, 49) pow[i + 1] = pow[i] * 2;
        vec<vec<vl>>a(n, vec<vl>(50, vl(2, inf)));
        vec<vec<H>>b(n, vec<H>(2, H{ inf, inf }));
        a[0][0][0] = 0;
        priority_queue<ps, vec<ps>, greater<ps>>pq;
        pq.push(ps{ 0,0,0,0 });
        while (!pq.empty()) {
            auto [v, t, c, ride] = pq.top();
            pq.pop();
            if (t < 40) {
                if (a[v][t][ride] != c) continue;
                for (auto g : e[v]) {
                    if (g.type) {
                        if (a[g.to][t + !ride][1] > c + g.cst + (ride ? 0 : pow[t])) {
                            a[g.to][t + !ride][1] = c + g.cst + (ride ? 0 : pow[t]);
                            pq.push(ps{ g.to, t + !ride, a[g.to][t + !ride][1], 1 });
                        }
                    }
                    else {
                        if (a[g.to][t][0] > c + g.cst) {
                            a[g.to][t][0] = c + g.cst;
                            pq.push(ps{ g.to, t, a[g.to][t][0], 0 });
                        }
                    }
                }
            }
            else if (t == 40) {
                if (a[v][t][ride] != c) continue;
                for (auto g : e[v]) {
                    if (g.type) {
                        if (ride) {
                            if (a[g.to][t][1] > c + g.cst) {
                                a[g.to][t][1] = c + g.cst;
                                pq.push(ps{ g.to, t, a[g.to][t][1], 1 });
                            }
                        }
                        else {
                            if (b[g.to][1] > H{ 41,c + g.cst }) {
                                b[g.to][1] = H{ 41, c + g.cst };
                                pq.push(ps{ g.to, 41, b[g.to][1].sc, 1 });
                            }
                        }
                    }
                    else {
                        if (a[g.to][t][0] > c + g.cst) {
                            a[g.to][t][0] = c + g.cst;
                            pq.push(ps{ g.to, t, a[g.to][t][0], 0 });
                        }
                    }
                }
            }
            else {
                if (b[v][ride] != H{ t, c }) continue;
                for (auto g : e[v]) {
                    if (g.type) {
                        if (b[g.to][1] > H{ t + !ride, c + g.cst }) {
                            b[g.to][1] = H{ t + !ride, c + g.cst };
                            pq.push(ps{ g.to, t + !ride, b[g.to][1].sc, 1 });
                        }
                    }
                    else {
                        if (b[g.to][0] > H{ t, c + g.cst }) {
                            b[g.to][0] = H{ t, c + g.cst };
                            pq.push(ps{ g.to, t, b[g.to][0].sc, 0 });
                        }
                    }
                }
            }
        }
        ll ans = inf;
        rep(i, 50) rep(j, 2) chmin(ans, a[n - 1][i][j]);
        if (ans == inf) {
            H res = min(b[n - 1][0], b[n - 1][1]);
            if (res.fs == inf) ans = -1;
            else {
                ll tmp = 1;
                ans = 0;
                rep(i, res.fs) {
                    if (i >= 40) (ans += tmp) %= 1000000007;
                    (tmp *= 2) %= 1000000007;
                }// ;
                ans += res.sc;
            }
        }
        cout << ans % 1000000007 << endl;
    }
}
//564049465049187
//1125899906842723

//1126999418470499
accuracy: 1
time_ms: 1860
memory_kb: 65888
final_rank: 13

code_snippet: // # pragma GCC target("avx2")
// # pragma GCC optimize("O3")
// # pragma GCC optimize("unroll-loops")
// #define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;

using ll = long long; using vl = vector<ll>; using vvl = vector<vl>; using vvvl = vector<vvl>;
#include <atcoder/modint>
#include <atcoder/math>
using namespace atcoder;
// using mint = modint998244353;
// const ll MOD = 998244353;
// // using mint = modint;
// // const ll MOD = 998244353;
using mint = modint1000000007;
const ll MOD = 1000000007;
using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>;

#define rep(i, a, b) for(long long i = (a); i < (b); i++) // [a, b)を昇順に
// #define rep(i, n) for (int i = 0; i < (n); i++)
#define rep2(i, a, b) for (int i = (a); i < (b); i++)
#define drep(i, a, b) for(long long i = (b) - 1; i >= a; i--) // [a, b)を降順に
#define rrep(i, n) for (int i = (n) - 1; i >= 0; i--)
#define all(v) v.begin(), v.end() // 昇順sortに
#define rall(v) v.rbegin(), v.rend() // 降順sortに
#define sz(x) (int)(x).size()
#define decimal(n) cout << fixed << setprecision(n);
#define debug(x) cerr << #x << " = " << x << endl;
#define Yes cout << "Yes" << endl;
#define No cout << "No" << endl;
#define yesno(condition) { if (condition) cout << "Yes" << endl; else cout << "No" << endl; }
using vi = vector<int>; using vvi = vector<vi>; using vs = vector<string>;
using lll = __int128;
using P = pair<ll, ll>; using T = tuple<ll, ll, ll>;
using vc = vector<char>;
const ll MAX = 5'000'009; const ll llINF = 2e18;
const int intINF = 2e9; const long double pi = acos(-1);
const long long INF = 1000000000000000005LL;
ll di[] = {0, -1, 0, 1, -1, -1, 1, 1};
ll dj[] = {1, 0, -1, 0, 1, -1, -1, 1};
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
template<class T> using pq = priority_queue<T, vector<T>>; //大きい順
template<class T> using pq_g = priority_queue<T, vector<T>, greater<T>>; //小さい順

bool isin(ll i, ll j, ll n, ll m) { return (0 <= i && i < n && 0 <= j && j < m); }
bool is_multiple_overflow(ll a, ll b, ll c) {
  // a * b > cかを判定する
  if (a == 0 || b == 0) return false;
  return (a <= c / b ? false : true);
}

void dijkstra(long long start, vector<vector<pair<long long, long long>>> &G, vector<long long> &dist){
    // pair(cost,vertex)の順で入っていく
    priority_queue<pair<long long, long long>,vector<pair<long long, long long>>,greater<pair<long long, long long>>> q;

    dist.resize(int(G.size()));
    fill(all(dist), llINF);

    dist[start] = 0;
    q.push(make_pair(0, start));

    while(!q.empty()){
        auto [time, cur_v] = q.top();
        q.pop();
        if(dist[cur_v] != time) {
            continue;
        }
        for(auto p : G[cur_v]){
            long long next_v = p.first; long long cost = p.second;

            if(dist[next_v] > dist[cur_v] + cost){
                dist[next_v] = dist[cur_v] + cost;
                q.push(make_pair(dist[next_v], next_v));
            }
        }
    }
}

void dijkstra2(ll start, vector<vector<T>> &G, vector<P> &dist){
    priority_queue<pair<P, ll>,vector<pair<P, ll>>,greater<pair<P, ll>>> q; // pair(cost,vertex)の順で入っていく

    dist.resize(sz(G));
    rep(i, 0, sz(G)) dist[i] = {llINF, llINF};
    dist[start] = {0ll ,0ll};
    q.push(make_pair(dist[start], start));

    while(!q.empty()){
        auto [time, now] = q.top();
        q.pop();
        if(dist[now] != time) {
            continue;
        }
        for(auto p : G[now]){
            ll go = get<0>(p), taxicost = get<1>(p), timecost = get<2>(p);
            P next = {time.first + taxicost, time.second + timecost};

            if(dist[go] > next){
                dist[go] = next;
                q.push(make_pair(dist[go], go));
            }
        }
    }
}

void solve(ll n, ll p, ll q) {
    vl a(p), b(p), c(p);
    rep(i, 0, p) {
        cin >> a[i] >> b[i] >> c[i];
        a[i]--; b[i]--;
    }
    vl d(q), e(q), f(q);
    rep(i, 0, q) {
        cin >> d[i] >> e[i] >> f[i];
        d[i]--; e[i]--;
    }

    ll mt = 45;
    vector<vector<P>> G(2 * mt * n);
    rep(i, 0, n) {
        rep(j, 0, 2 * mt - 1) {
            G[i + j * n].emplace_back(P({i + j * n + n, 0ll}));
        }
    }
    rep(i, 0, mt) {
        rep(j, 0, p) {
            G[2 * i * n + a[j]].emplace_back(P({2 * i * n + b[j], c[j]}));
            G[2 * i * n + b[j]].emplace_back(P({2 * i * n + a[j], c[j]}));
        }
    }
    rep(i, 0, mt - 1) {
        rep(j, 0, q) {
            G[(2 * i + 1) * n + d[j]].emplace_back(P({(2 * i + 1) * n + e[j]}, f[j]));
            G[(2 * i + 1) * n + e[j]].emplace_back(P({(2 * i + 1) * n + d[j]}, f[j]));
        }
    }

    vl dist;
    dijkstra(0ll, G, dist);

    vl pena(mt);
    pena[0] = 0;
    rep(i, 0, mt - 1) {
        pena[i + 1] = pena[i] * 2 + 1;
    }

    ll ans = llINF;
    for(ll i =  n - 1; i < 2 * mt * n; i += 2 * n){
        if(dist[i] == llINF) continue;
        chmin(ans, dist[i] + pena[i / (2 * n)]);
    }
    if(ans != llINF) ans %= MOD;

    vector<vector<T>> G2(2 * n);
    rep(i, 0, n) {
        G2[i].emplace_back(T({i + n, 1ll, 0ll}));
        G2[i + n].emplace_back(T({i, 0ll, 0ll}));
    }
    rep(i, 0, p) {
        G2[a[i]].emplace_back(T({b[i], 0ll, c[i]}));
        G2[b[i]].emplace_back(T({a[i], 0ll, c[i]}));
    }
    rep(i, 0, q) {
        G2[n + d[i]].emplace_back(T({n + e[i], 0ll, f[i]}));
        G2[n + e[i]].emplace_back(T({n + d[i], 0ll, f[i]}));
    }

    vector<P> dist2;
    dijkstra2(0, G2, dist2);

    if(dist2[n - 1].first != llINF && dist2[n - 1].first >= mt) {
        ans = dist2[n - 1].second + pow_mod(2ll, dist2[n - 1].first, MOD) - 1 + MOD;
        ans %= MOD;
    }

    if(ans == llINF) cout << -1 << endl;
    else cout << ans << endl;
    return ;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  
    while(true) {
        ll n, p, q;
        cin >> n >> p >> q;
        if(n == 0) return 0;
        solve(n, p, q);
    }

  return 0;
}
accuracy: 1
time_ms: 5500
memory_kb: 215344
final_rank: 20

code_snippet: // # pragma GCC target("avx2")
// # pragma GCC optimize("O3")
// # pragma GCC optimize("unroll-loops")
// #define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;

using ll = long long; using vl = vector<ll>; using vvl = vector<vl>; using vvvl = vector<vvl>;
#include <atcoder/modint>
#include <atcoder/math>
using namespace atcoder;
// using mint = modint998244353;
// const ll MOD = 998244353;
// // using mint = modint;
// // const ll MOD = 998244353;
using mint = modint1000000007;
const ll MOD = 1000000007;
using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>;

#define rep(i, a, b) for(long long i = (a); i < (b); i++) // [a, b)を昇順に
// #define rep(i, n) for (int i = 0; i < (n); i++)
#define rep2(i, a, b) for (int i = (a); i < (b); i++)
#define drep(i, a, b) for(long long i = (b) - 1; i >= a; i--) // [a, b)を降順に
#define rrep(i, n) for (int i = (n) - 1; i >= 0; i--)
#define all(v) v.begin(), v.end() // 昇順sortに
#define rall(v) v.rbegin(), v.rend() // 降順sortに
#define sz(x) (int)(x).size()
#define decimal(n) cout << fixed << setprecision(n);
#define debug(x) cerr << #x << " = " << x << endl;
#define Yes cout << "Yes" << endl;
#define No cout << "No" << endl;
#define yesno(condition) { if (condition) cout << "Yes" << endl; else cout << "No" << endl; }
using vi = vector<int>; using vvi = vector<vi>; using vs = vector<string>;
using lll = __int128;
using P = pair<ll, ll>; using T = tuple<ll, ll, ll>;
using vc = vector<char>;
const ll MAX = 5'000'009; const ll llINF = 2e18;
const int intINF = 2e9; const long double pi = acos(-1);
const long long INF = 1000000000000000005LL;
ll di[] = {0, -1, 0, 1, -1, -1, 1, 1};
ll dj[] = {1, 0, -1, 0, 1, -1, -1, 1};
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
template<class T> using pq = priority_queue<T, vector<T>>; //大きい順
template<class T> using pq_g = priority_queue<T, vector<T>, greater<T>>; //小さい順

bool isin(ll i, ll j, ll n, ll m) { return (0 <= i && i < n && 0 <= j && j < m); }
bool is_multiple_overflow(ll a, ll b, ll c) {
  // a * b > cかを判定する
  if (a == 0 || b == 0) return false;
  return (a <= c / b ? false : true);
}

void dijkstra(ll start, vector<vector<P>> &G, vl &dist){
    priority_queue<P,vector<P>,greater<P>> q; // pair(cost,vertex)の順で入っていく

    dist.resize(sz(G));
    rep(i, 0, sz(G)) dist[i] = llINF;
    dist[start] = 0;
    q.push(make_pair(0, start));

    while(!q.empty()){
        auto [time, now] = q.top();
        q.pop();
        if(dist[now] != time) {
            continue;
        }
        for(auto p : G[now]){
            ll go = p.first; ll cost = p.second;

            if(dist[go] > dist[now] + cost){
                dist[go] = dist[now] + cost;
                q.push(make_pair(dist[go], go));
            }
        }
    }
}

void dijkstra2(ll start, vector<vector<T>> &G, vector<P> &dist){
    priority_queue<pair<P, ll>,vector<pair<P, ll>>,greater<pair<P, ll>>> q; // pair(cost,vertex)の順で入っていく

    dist.resize(sz(G));
    rep(i, 0, sz(G)) dist[i] = {llINF, llINF};
    dist[start] = {0ll ,0ll};
    q.push(make_pair(dist[start], start));

    while(!q.empty()){
        auto [time, now] = q.top();
        q.pop();
        if(dist[now] != time) {
            continue;
        }
        for(auto p : G[now]){
            ll go = get<0>(p), taxicost = get<1>(p), timecost = get<2>(p);
            P next = {time.first + taxicost, time.second + timecost};

            if(dist[go] > next){
                dist[go] = next;
                q.push(make_pair(dist[go], go));
            }
        }
    }
}

void solve(ll n, ll p, ll q) {
    vl a(p), b(p), c(p);
    rep(i, 0, p) {
        cin >> a[i] >> b[i] >> c[i];
        a[i]--; b[i]--;
    }
    vl d(q), e(q), f(q);
    rep(i, 0, q) {
        cin >> d[i] >> e[i] >> f[i];
        d[i]--; e[i]--;
    }

    ll mt = 45;
    vector<vector<P>> G(2 * mt * n);
    rep(i, 0, n) {
        rep(j, 0, 2 * mt - 1) {
            G[i + j * n].emplace_back(P({i + j * n + n, 0ll}));
        }
    }
    rep(i, 0, mt) {
        rep(j, 0, p) {
            G[2 * i * n + a[j]].emplace_back(P({2 * i * n + b[j], c[j]}));
            G[2 * i * n + b[j]].emplace_back(P({2 * i * n + a[j], c[j]}));
        }
    }
    rep(i, 0, mt - 1) {
        rep(j, 0, q) {
            G[(2 * i + 1) * n + d[j]].emplace_back(P({(2 * i + 1) * n + e[j]}, f[j]));
            G[(2 * i + 1) * n + e[j]].emplace_back(P({(2 * i + 1) * n + d[j]}, f[j]));
        }
    }

    vl dist;
    dijkstra(0ll, G, dist);

    vl pena(mt);
    pena[0] = 0;
    rep(i, 0, mt - 1) {
        pena[i + 1] = pena[i] * 2 + 1;
    }

    ll ans = llINF;
    for(ll i =  n - 1; i < 2 * mt * n; i += 2 * n){
        if(dist[i] == llINF) continue;
        chmin(ans, dist[i] + pena[i / (2 * n)]);
    }
    if(ans != llINF) ans %= MOD;

    vector<vector<T>> G2(2 * n);
    rep(i, 0, n) {
        G2[i].emplace_back(T({i + n, 1ll, 0ll}));
        G2[i + n].emplace_back(T({i, 0ll, 0ll}));
    }
    rep(i, 0, p) {
        G2[a[i]].emplace_back(T({b[i], 0ll, c[i]}));
        G2[b[i]].emplace_back(T({a[i], 0ll, c[i]}));
    }
    rep(i, 0, q) {
        G2[n + d[i]].emplace_back(T({n + e[i], 0ll, f[i]}));
        G2[n + e[i]].emplace_back(T({n + d[i], 0ll, f[i]}));
    }

    vector<P> dist2;
    dijkstra2(0, G2, dist2);

    if(dist2[n - 1].first != llINF && dist2[n - 1].first >= mt) {
        ans = dist2[n - 1].second + pow_mod(2ll, dist2[n - 1].first, MOD) - 1 + MOD;
        ans %= MOD;
    }

    if(ans == llINF) cout << -1 << endl;
    else cout << ans << endl;
    return ;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  
    while(true) {
        ll n, p, q;
        cin >> n >> p >> q;
        if(n == 0) return 0;
        solve(n, p, q);
    }

  return 0;
}
accuracy: 1
time_ms: 5460
memory_kb: 215060
final_rank: 19

code_snippet: // # pragma GCC target("avx2")
// # pragma GCC optimize("O3")
// # pragma GCC optimize("unroll-loops")
// #define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;

using ll = long long; using vl = vector<ll>; using vvl = vector<vl>; using vvvl = vector<vvl>;
#include <atcoder/modint>
#include <atcoder/math>
using namespace atcoder;
// using mint = modint998244353;
// const ll MOD = 998244353;
// // using mint = modint;
// // const ll MOD = 998244353;
using mint = modint1000000007;
const ll MOD = 1000000007;
using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>;

#define rep(i, a, b) for(long long i = (a); i < (b); i++) // [a, b)を昇順に
// #define rep(i, n) for (int i = 0; i < (n); i++)
#define rep2(i, a, b) for (int i = (a); i < (b); i++)
#define drep(i, a, b) for(long long i = (b) - 1; i >= a; i--) // [a, b)を降順に
#define rrep(i, n) for (int i = (n) - 1; i >= 0; i--)
#define all(v) v.begin(), v.end() // 昇順sortに
#define rall(v) v.rbegin(), v.rend() // 降順sortに
#define sz(x) (int)(x).size()
#define decimal(n) cout << fixed << setprecision(n);
#define debug(x) cerr << #x << " = " << x << endl;
#define Yes cout << "Yes" << endl;
#define No cout << "No" << endl;
#define yesno(condition) { if (condition) cout << "Yes" << endl; else cout << "No" << endl; }
using vi = vector<int>; using vvi = vector<vi>; using vs = vector<string>;
using lll = __int128;
using P = pair<ll, ll>; using T = tuple<ll, ll, ll>;
using vc = vector<char>;
const ll MAX = 5'000'009; const ll llINF = 2e18;
const int intINF = 2e9; const long double pi = acos(-1);
const long long INF = 1000000000000000005LL;
ll di[] = {0, -1, 0, 1, -1, -1, 1, 1};
ll dj[] = {1, 0, -1, 0, 1, -1, -1, 1};
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
template<class T> using pq = priority_queue<T, vector<T>>; //大きい順
template<class T> using pq_g = priority_queue<T, vector<T>, greater<T>>; //小さい順

bool isin(ll i, ll j, ll n, ll m) { return (0 <= i && i < n && 0 <= j && j < m); }
bool is_multiple_overflow(ll a, ll b, ll c) {
  // a * b > cかを判定する
  if (a == 0 || b == 0) return false;
  return (a <= c / b ? false : true);
}

void dijkstra(ll start, vector<vector<P>> &G, vl &dist){
    priority_queue<P,vector<P>,greater<P>> q; // pair(cost,vertex)の順で入っていく

    dist.resize(sz(G));
    rep(i, 0, sz(G)) dist[i] = llINF;
    dist[start] = 0;
    q.push(make_pair(0, start));

    while(!q.empty()){
        auto [time, now] = q.top();
        q.pop();
        if(dist[now] != time) {
            continue;
        }
        for(auto p : G[now]){
            ll go = p.first; ll cost = p.second;

            if(dist[go] > dist[now] + cost){
                dist[go] = dist[now] + cost;
                q.push(make_pair(dist[go], go));
            }
        }
    }
}

void dijkstra2(ll start, vector<vector<T>> &G, vector<P> &dist){
    priority_queue<pair<P, ll>,vector<pair<P, ll>>,greater<pair<P, ll>>> q; // pair(cost,vertex)の順で入っていく

    dist.resize(sz(G));
    rep(i, 0, sz(G)) dist[i] = {llINF, llINF};
    dist[start] = {0ll ,0ll};
    q.push(make_pair(dist[start], start));

    while(!q.empty()){
        auto [time, now] = q.top();
        q.pop();
        if(dist[now] != time) {
            continue;
        }
        for(auto p : G[now]){
            ll go = get<0>(p), taxicost = get<1>(p), travelcost = get<2>(p);
            P next = {time.first + taxicost, time.second + travelcost};

            if(dist[go] > next){
                dist[go] = next;
                q.push(make_pair(dist[go], go));
            }
        }
    }
}

void solve(ll n, ll p, ll q) {
    vl a(p), b(p), c(p);
    rep(i, 0, p) {
        cin >> a[i] >> b[i] >> c[i];
        a[i]--; b[i]--;
    }
    vl d(q), e(q), f(q);
    rep(i, 0, q) {
        cin >> d[i] >> e[i] >> f[i];
        d[i]--; e[i]--;
    }

    ll mt = 40;
    vector<vector<P>> G(2 * mt * n);
    rep(i, 0, n) {
        rep(j, 0, 2 * mt - 1) {
            G[i + j * n].emplace_back(P({i + j * n + n, 0ll}));
        }
    }
    rep(i, 0, mt) {
        rep(j, 0, p) {
            G[2 * i * n + a[j]].emplace_back(P({2 * i * n + b[j], c[j]}));
            G[2 * i * n + b[j]].emplace_back(P({2 * i * n + a[j], c[j]}));
        }
    }
    rep(i, 0, mt - 1) {
        rep(j, 0, q) {
            G[(2 * i + 1) * n + d[j]].emplace_back(P({(2 * i + 1) * n + e[j]}, f[j]));
            G[(2 * i + 1) * n + e[j]].emplace_back(P({(2 * i + 1) * n + d[j]}, f[j]));
        }
    }

    vl dist;
    dijkstra(0ll, G, dist);

    vl pena(mt);
    pena[0] = 0;
    rep(i, 0, mt - 1) {
        pena[i + 1] = pena[i] * 2 + 1;
    }

    ll ans = llINF;
    for(ll i = n - 1; i < 2 * mt * n; i += 2 * n){
        if(dist[i] == llINF) continue;

        chmin(ans, dist[i] + pena[i / (2 * n)]);
    }

    if(ans != llINF) {
        ans %= MOD;
        cout << ans << endl;
        return ;
    }

    vector<vector<T>> G2(2 * n);
    rep(i, 0, n) {
        G2[i].emplace_back(T({i + n, 1ll, 0ll}));
        G2[i + n].emplace_back(T({i, 0ll, 0ll}));
    }
    rep(i, 0, p) {
        G2[a[i]].emplace_back(T({b[i], 0ll, c[i]}));
        G2[b[i]].emplace_back(T({a[i], 0ll, c[i]}));
    }
    rep(i, 0, q) {
        G2[n + d[i]].emplace_back(T({n + e[i], 0ll, f[i]}));
        G2[n + e[i]].emplace_back(T({n + d[i], 0ll, f[i]}));
    }

    vector<P> dist2;
    dijkstra2(0, G2, dist2);

    assert(dist2[n - 1].first >= mt);

    if(dist2[n - 1].first == llINF) {
        cout << -1 << endl;
    }
    else {
        ans = dist2[n - 1].second + pow_mod(2ll, dist2[n - 1].first, MOD) - 1 + MOD;
        ans %= MOD;
        cout << ans << endl;
    }
    return ;

    // if(dist2[n - 1].first != llINF && dist2[n - 1].first >= mt) {
    // }
    // else assert(false);

    // if(ans == llINF) cout << -1 << endl;
    // else cout << ans << endl;
    // return ;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  
    while(true) {
        ll n, p, q;
        cin >> n >> p >> q;
        if(n == 0) return 0;
        solve(n, p, q);
    }

  return 0;
}
accuracy: 1
time_ms: 4560
memory_kb: 190660
final_rank: 17

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

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
#define rep3(i, a, b, c) for (ll i = (a); i < (b); i += (c))
#define rep2(i, a, b) rep3(i, a, b, 1)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(aaaaa, n)
#define ov4(a, b, c, d, name, ...) name
#define rep(...) ov4(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__)
#define per(i, a, b) for (ll i = (a) - 1; i >= (b); i--)
#define fore(e, v) for (auto&& e : v)
#define all(a) begin(a), end(a)
#define sz(a) (int)(size(a))
#define lb(v, x) (lower_bound(all(v), x) - begin(v))
#define eb emplace_back

template <typename T, typename S>
bool chmin(T& a, const S& b) {
  return a > b ? a = b, 1 : 0;
}
template <typename T, typename S>
bool chmax(T& a, const S& b) {
  return a < b ? a = b, 1 : 0;
}
const int INF = 1e9 + 100;
const ll INFL = 3e18 + 100;
#define i128 __int128_t
struct _ {
  _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;


int main(){
  const int M = 36;
  const ll mod = 1e9 + 7;
  while (true) {
    int n, p, q; cin >> n >> p >> q;
    if (n == 0) break;
    vector<vector<pii>> g1(n), g2(n);
    rep(i, p) {
      int a, b, c;cin >> a >> b >> c;
      a--, b--;
      g1[a].emplace_back(b, c);
      g1[b].emplace_back(a, c);
    }
    rep(i, q) {
      int a, b, c;cin >> a >> b >> c;
      a--, b--;
      g2[a].emplace_back(b, c);
      g2[b].emplace_back(a, c);
    }

    using S = pair<int, ll>;
    using T = tuple<int, ll, int>;
    vector<vector<S>> dist(n * 2, vector<S>(M, S{INF, INFL}));
    
    priority_queue<T,vector<T>, greater<T>> pq;
    // cerr << "!" << endl;
    dist[0][0] = S{0, 0};
    pq.emplace(T{0, 0, 0});
    while(!pq.empty()) {
      auto [cnt, d, v] = pq.top();pq.pop();
      // cerr << cnt << " " << d << " " << v+1 << endl;
      if (S{cnt, d} != dist[v][min(M-1, cnt)]) continue;
      if (v >= n) {
        for(auto [u,cost] : g2[v-n]) {
          S nd = S{cnt, d + cost};
          T nt = T{cnt, d + cost, u + n};
          if (dist[u+n][min(M-1, cnt)] > nd) {
            dist[u+n][min(M-1, cnt)] = nd;
            pq.emplace(T{nd.first, nd.second, u + n});
          }
        }
        S nd = S{cnt, d};
        if (dist[v-n][min(M-1, cnt)] > nd) {
          dist[v-n][min(M-1, cnt)] = nd;
          pq.emplace(T{nd.first, nd.second, v-n});
        }
      }else {
        S nd = S{cnt+1, d};
        if (dist[v+n][min(M-1, cnt+1)] > nd) {
          dist[v+n][min(M-1, cnt+1)] = nd;
          pq.emplace(nd.first, nd.second, v + n);
        }
      
        for(auto [u,cost] : g1[v]) {
          S nd = S{cnt, d + cost};
          if (dist[u][min(M-1, cnt)] > nd) {
            dist[u][min(M-1, cnt)] = nd;
            pq.emplace(nd.first, nd.second, u);
          }
        }
      }
    }

    // rep(i, n) {
    //   rep(j, M) {
    //     cerr << dist[i][j].first << "/" << dist[i][j].second << " ";
    //   }
    //   cerr << endl;
    // }

    ll ans = INFL;
    rep(i, M-1) {
      if (dist[n-1][i].first != INF) chmin(ans, (1ll<<i) - 1 + dist[n-1][i].second);
      // cerr << i << " " << (1ll<<i) - 1 + dist[n-1][i].second << endl;
    }
    if (ans != INFL) {
      cout << ans % mod << endl;
    }
    else if(dist[n-1].back().first == INF) {
      cout << -1 << endl;
    }
    else {
      ll ans = 1;
      auto [cnt, l] = dist[n-1].back();
      rep(i, cnt) {
        ans = ans * 2 % mod;
      }
      ans = (ans + mod-1) % mod;
      cout << (ans + l) % mod << endl;
    }
  }
}
accuracy: 1
time_ms: 1140
memory_kb: 32160
final_rank: 3

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

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
#define rep3(i, a, b, c) for (ll i = (a); i < (b); i += (c))
#define rep2(i, a, b) rep3(i, a, b, 1)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(aaaaa, n)
#define ov4(a, b, c, d, name, ...) name
#define rep(...) ov4(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__)
#define per(i, a, b) for (ll i = (a) - 1; i >= (b); i--)
#define fore(e, v) for (auto&& e : v)
#define all(a) begin(a), end(a)
#define sz(a) (int)(size(a))
#define lb(v, x) (lower_bound(all(v), x) - begin(v))
#define eb emplace_back

template <typename T, typename S>
bool chmin(T& a, const S& b) {
  return a > b ? a = b, 1 : 0;
}
template <typename T, typename S>
bool chmax(T& a, const S& b) {
  return a < b ? a = b, 1 : 0;
}
const int INF = 1e9 + 100;
const ll INFL = 3e18 + 100;
#define i128 __int128_t
struct _ {
  _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;


int main(){
  const int M = 40;
  const ll mod = 1e9 + 7;
  while (true) {
    int n, p, q; cin >> n >> p >> q;
    if (n == 0) break;
    vector<vector<pii>> g1(n), g2(n);
    rep(i, p) {
      int a, b, c;cin >> a >> b >> c;
      a--, b--;
      g1[a].emplace_back(b, c);
      g1[b].emplace_back(a, c);
    }
    rep(i, q) {
      int a, b, c;cin >> a >> b >> c;
      a--, b--;
      g2[a].emplace_back(b, c);
      g2[b].emplace_back(a, c);
    }

    using S = pair<int, ll>;
    using T = tuple<int, ll, int>;
    vector<vector<S>> dist(n * 2, vector<S>(M, S{INF, INFL}));
    
    priority_queue<T,vector<T>, greater<T>> pq;
    // cerr << "!" << endl;
    dist[0][0] = S{0, 0};
    pq.emplace(T{0, 0, 0});
    while(!pq.empty()) {
      auto [cnt, d, v] = pq.top();pq.pop();
      // cerr << cnt << " " << d << " " << v+1 << endl;
      if (S{cnt, d} != dist[v][min(M-1, cnt)]) continue;
      if (v >= n) {
        for(auto [u,cost] : g2[v-n]) {
          S nd = S{cnt, d + cost};
          T nt = T{cnt, d + cost, u + n};
          if (dist[u+n][min(M-1, cnt)] > nd) {
            dist[u+n][min(M-1, cnt)] = nd;
            pq.emplace(T{nd.first, nd.second, u + n});
          }
        }
        S nd = S{cnt, d};
        if (dist[v-n][min(M-1, cnt)] > nd) {
          dist[v-n][min(M-1, cnt)] = nd;
          pq.emplace(T{nd.first, nd.second, v-n});
        }
      }else {
        S nd = S{cnt+1, d};
        if (dist[v+n][min(M-1, cnt+1)] > nd) {
          dist[v+n][min(M-1, cnt+1)] = nd;
          pq.emplace(nd.first, nd.second, v + n);
        }
      
        for(auto [u,cost] : g1[v]) {
          S nd = S{cnt, d + cost};
          if (dist[u][min(M-1, cnt)] > nd) {
            dist[u][min(M-1, cnt)] = nd;
            pq.emplace(nd.first, nd.second, u);
          }
        }
      }
    }

    // rep(i, n) {
    //   rep(j, M) {
    //     cerr << dist[i][j].first << "/" << dist[i][j].second << " ";
    //   }
    //   cerr << endl;
    // }

    ll ans = INFL;
    rep(i, M-1) {
      if (dist[n-1][i].first != INF) chmin(ans, (1ll<<i) - 1 + dist[n-1][i].second);
      // cerr << i << " " << (1ll<<i) - 1 + dist[n-1][i].second << endl;
    }
    if (ans != INFL) {
      cout << ans % mod << endl;
    }
    else if(dist[n-1].back().first == INF) {
      cout << -1 << endl;
    }
    else {
      ll ans = 1;
      auto [cnt, l] = dist[n-1].back();
      rep(i, cnt) {
        ans = ans * 2 % mod;
      }
      ans = (ans + mod-1) % mod;
      cout << (ans + l) % mod << endl;
    }
  }
}
accuracy: 1
time_ms: 1270
memory_kb: 34660
final_rank: 4

code_snippet: #include <bits/extc++.h>

#include <atcoder/all>

using mint = atcoder::modint1000000007;

using ll = long long;

using pii = std::pair<int, int>;
using pil = std::pair<int, ll>;

template <class T>
using pq_rev = std::priority_queue<T, std::vector<T>, std::greater<>>;

template <class T>
bool chmax(T& x, const T& v) {
  if (x < v) {
    x = v;
    return true;
  } else {
    return false;
  }
}
template <class T>
bool chmin(T& x, const T& v) {
  if (x > v) {
    x = v;
    return true;
  } else {
    return false;
  }
}

using node = std::tuple<ll, mint, int, int, int>;

struct compare {
  bool operator()(node l, node r) {
    auto [al, bl, cl, dl, el] = l;
    auto [ar, br, cr, dr, er] = r;
    if (el < 60 && er < 60) {
      return al + (1LL << el) > ar + (1LL << er);
    } else {
      return el > er || (el == er && al > ar);
    }
  }
} cmp;

bool solve() {
  int N, P, Q;
  std::cin >> N >> P >> Q;
  if (N == 0) {
    return false;
  }

  std::vector walk(N, std::vector<pil>());
  std::vector taxi(N, std::vector<pil>());

  for (int i = 0; i < P; i++) {
    int a, b;
    ll c;
    std::cin >> a >> b >> c;

    a--, b--;

    walk[a].emplace_back(b, c);
    walk[b].emplace_back(a, c);
  }

  for (int i = 0; i < Q; i++) {
    int a, b;
    ll c;
    std::cin >> a >> b >> c;

    a--, b--;

    taxi[a].emplace_back(b, c);
    taxi[b].emplace_back(a, c);
  }

  atcoder::dsu dsu(N);

  for (int i = 0; i < N; i++) {
    for (auto [w, c] : walk[i]) {
      dsu.merge(i, w);
    }
    for (auto [w, c] : taxi[i]) {
      dsu.merge(i, w);
    }
  }

  if (!dsu.same(0, N - 1)) {
    std::cout << "-1\n";
    return true;
  }

  std::priority_queue<node, std::vector<node>, compare> priq;

  std::vector dist(
      N, std::vector(2, std::vector<node>(60, node(0, 0, 0, 0, 10000000))));
  std::vector locked(N, std::vector(2, std::vector(60, false)));

  dist[0][0][0] = {0, 0, 0, 0, 0};

  priq.emplace(0, 0, 0, 0, 0);

  auto move = [&](int v, int tx, int tc, node r) {
    if (!locked[v][tx][tc] && cmp(dist[v][tx][tc], r)) {
      dist[v][tx][tc] = r;
      priq.emplace(r);
    }
  };

  while (!priq.empty()) {
    node nodev = priq.top();
    auto [dl, dm, v, tx, tc] = nodev;
    priq.pop();

    if (v == N - 1) {
      std::cout << dm.val() << '\n';
      break;
    }

    int tc2 = std::min(tc, 59);

    if (locked[v][tx][tc2]) continue;

    locked[v][tx][tc2] = true;

    if (tx) {
      move(v, 0, tc2, {dl, dm, v, 0, tc});

      for (auto [w, c] : taxi[v]) {
        move(w, 1, tc2, {dl + c, dm + c, w, 1, tc});
      }
    } else {
      move(v, 1, std::min(tc2 + 1, 59),
           {dl, dm + mint(2).pow(tc), v, 1, tc + 1});

      for (auto [w, c] : walk[v]) {
        move(w, 0, tc2, {dl + c, dm + c, w, 0, tc});
      }
    }
  }

  return true;
}

int main() {
  while (solve());
}
accuracy: 1
time_ms: 1260
memory_kb: 80280
final_rank: 9

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

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
#define rep3(i, a, b, c) for (ll i = (a); i < (b); i += (c))
#define rep2(i, a, b) rep3(i, a, b, 1)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(aaaaa, n)
#define ov4(a, b, c, d, name, ...) name
#define rep(...) ov4(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__)
#define per(i, a, b) for (ll i = (a) - 1; i >= (b); i--)
#define fore(e, v) for (auto&& e : v)
#define all(a) begin(a), end(a)
#define sz(a) (int)(size(a))
#define lb(v, x) (lower_bound(all(v), x) - begin(v))
#define eb emplace_back

template <typename T, typename S>
bool chmin(T& a, const S& b) {
  return a > b ? a = b, 1 : 0;
}
template <typename T, typename S>
bool chmax(T& a, const S& b) {
  return a < b ? a = b, 1 : 0;
}
const int INF = 1e9 + 100;
const ll INFL = 3e18 + 100;
#define i128 __int128_t
struct _ {
  _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;


int main(){
  const int M = 50;
  const ll mod = 1e9 + 7;
  while (true) {
    int n, p, q; cin >> n >> p >> q;
    if (n == 0) break;
    vector<vector<pii>> g1(n), g2(n);
    rep(i, p) {
      int a, b, c;cin >> a >> b >> c;
      a--, b--;
      g1[a].emplace_back(b, c);
      g1[b].emplace_back(a, c);
    }
    rep(i, q) {
      int a, b, c;cin >> a >> b >> c;
      a--, b--;
      g2[a].emplace_back(b, c);
      g2[b].emplace_back(a, c);
    }

    using S = pair<int, ll>;
    using T = tuple<int, ll, int>;
    vector<vector<S>> dist(n * 2, vector<S>(M, S{INF, INFL}));
    
    priority_queue<T,vector<T>, greater<T>> pq;
    // cerr << "!" << endl;
    dist[0][0] = S{0, 0};
    pq.emplace(T{0, 0, 0});
    while(!pq.empty()) {
      auto [cnt, d, v] = pq.top();pq.pop();
      // cerr << cnt << " " << d << " " << v+1 << endl;
      if (S{cnt, d} != dist[v][min(M-1, cnt)]) continue;
      if (v >= n) {
        for(auto [u,cost] : g2[v-n]) {
          S nd = S{cnt, d + cost};
          T nt = T{cnt, d + cost, u + n};
          if (dist[u+n][min(M-1, cnt)] > nd) {
            dist[u+n][min(M-1, cnt)] = nd;
            pq.emplace(T{nd.first, nd.second, u + n});
          }
        }
        S nd = S{cnt, d};
        if (dist[v-n][min(M-1, cnt)] > nd) {
          dist[v-n][min(M-1, cnt)] = nd;
          pq.emplace(T{nd.first, nd.second, v-n});
        }
      }else {
        S nd = S{cnt+1, d};
        if (dist[v+n][min(M-1, cnt+1)] > nd) {
          dist[v+n][min(M-1, cnt+1)] = nd;
          pq.emplace(nd.first, nd.second, v + n);
        }
      
        for(auto [u,cost] : g1[v]) {
          S nd = S{cnt, d + cost};
          if (dist[u][min(M-1, cnt)] > nd) {
            dist[u][min(M-1, cnt)] = nd;
            pq.emplace(nd.first, nd.second, u);
          }
        }
      }
    }

    // rep(i, n) {
    //   rep(j, M) {
    //     cerr << dist[i][j].first << "/" << dist[i][j].second << " ";
    //   }
    //   cerr << endl;
    // }

    ll ans = INFL;
    rep(i, M-1) {
      if (dist[n-1][i].first != INF) chmin(ans, (1ll<<i) - 1 + dist[n-1][i].second);
      // cerr << i << " " << (1ll<<i) - 1 + dist[n-1][i].second << endl;
    }
    if (ans != INFL) {
      cout << ans % mod << endl;
    }
    else if(dist[n-1].back().first == INF) {
      cout << -1 << endl;
    }
    else {
      ll ans = 1;
      auto [cnt, l] = dist[n-1].back();
      rep(i, cnt) {
        ans = ans * 2 % mod;
      }
      ans = (ans + mod-1) % mod;
      cout << (ans + l) % mod << endl;
    }
  }
}
accuracy: 1
time_ms: 1660
memory_kb: 40908
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (ll i = s; i < (ll)(t); i++)
#define rrep(i, s, t) for(ll i = (ll)(t) - 1; i >= (ll)(s); i--)
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)

#define TT template<typename T>
TT using vec = vector<T>;
template<class T1, class T2> bool chmin(T1 &x, T2 y) { return x > y ? (x = y, true) : false; }
template<class T1, class T2> bool chmax(T1 &x, T2 y) { return x < y ? (x = y, true) : false; }

struct io_setup {
    io_setup() {
        ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        cout << fixed << setprecision(15);
    }
} io_setup;

const ll INF=1LL<<60;
const int MOD=1'000'000'007;

ll power(ll x,ll r){
    ll re=1,k=x;
    for(int i=0;i<60;i++){
        if(r>>i&1){
            re=(re*k)%MOD;
        }
        k=k*k%MOD;
    }
    return re;
}

int main() {
    while(1){
        int N,P,Q;
        cin>>N>>P>>Q;
        if(N==0)return 0;
        vector<vector<tuple<int,ll,int>>>G(N);
        rep(i,0,P){
            int a,b;
            ll c;
            cin>>a>>b>>c;
            a--;
            b--;
            G[a].push_back({b,c,0});
            G[b].push_back({a,c,0});
        }
        rep(i,0,Q){
            int d,e;
            ll f;
            cin>>d>>e>>f;
            d--;
            e--;
            G[d].push_back({e,f,1});
            G[e].push_back({d,f,1});
        }
        vector<ll>T(N,INF);
        {
            vector t2(N,vector<ll>(2,INF));
            t2[0][0]=0;
            deque<tuple<ll,int,int>>dq;
            dq.push_back({t2[0][0],0,0});
            while(dq.size()){
                auto[c,x,y]=dq.front();
                dq.pop_front();
                if(t2[x][y]<c)continue;
                if(y==0){
                    if(chmin(t2[x][1],t2[x][y]+1)){
                        dq.push_back({t2[x][1],x,1});
                    }
                }else{
                    if(chmin(t2[x][0],t2[x][y])){
                        dq.push_front({t2[x][0],x,0});
                    }
                }
                for(auto[i,e,t]:G[x]){
                    if(y!=t)continue;
                    if(chmin(t2[i][y],t2[x][y])){
                        dq.push_front({t2[i][y],i,y});
                    }
                }
            }
            rep(i,0,N)T[i]=min(t2[i][0],t2[i][1]);
        }
        if(T[N-1]==INF){
            cout<<-1<<endl;
            continue;
        }
        vector dp(N,vector(60,vector<ll>(2,INF)));
        dp[0][0][0]=0;
        {
            priority_queue<tuple<ll,int,int,int>,vector<tuple<ll,int,int,int>>,greater<tuple<ll,int,int,int>>>pq;
            pq.push({dp[0][0][0],0,0,0});
            while(pq.size()){
                auto[cost,x,y,z]=pq.top();
                pq.pop();
                if(dp[x][y][z]<cost)continue;
                if(z==0){
                    if(y+1<60&&chmin(dp[x][y+1][1],dp[x][y][z])){
                        pq.push({dp[x][y+1][1],x,y+1,1});
                    }
                }else{
                    if(chmin(dp[x][y][0],dp[x][y][z])){
                        pq.push({dp[x][y][0],x,y,0});
                    }
                }
                for(auto[i,e,t]:G[x]){
                    if(z!=t)continue;
                    int j=T[x]+y-T[i];
                    if(0<=j&&j<60&&chmin(dp[i][j][z],dp[x][y][z]+e)){
                        pq.push({dp[i][j][z],i,j,z});
                    }
                }
            }
        }
        vector<ll>D(60);
        rep(i,0,60)D[i]=min(dp[N-1][i][0],dp[N-1][i][1]);
        if(T[N-1]>60){
            rep(i,0,60){
                if(D[i]!=INF){
                    ll ans=power(2,T[N-1]+i)-1+D[i];
                    ans%=MOD;
                    if(ans<0)ans+=MOD;
                    cout<<ans<<endl;
                    break;
                }
            }
        }else{
            rep(i,0,60){
                if(D[i]==INF)continue;
                bool ok=true;
                rep(j,0,60){
                    if(D[j]==INF)continue;
                    __int128_t p=1,q=1;
                    rep(k,0,T[N-1]+i)p*=2;
                    rep(k,0,T[N-1]+j)q*=2;
                    p+=D[i];
                    q+=D[j];
                    if(p>q){
                        ok=false;
                        break;
                    }
                }
                if(ok){
                    ll ans=power(2,T[N-1]+i)-1+D[i];
                    ans%=MOD;
                    if(ans<0)ans+=MOD;
                    cout<<ans<<endl;
                    break;
                }
            }
        }
    }
    //     rep(i,0,60){
    //         if(D[i]==INF)continue;
    //         bool ok=true;
    //         rep(j,0,60){
    //             if(D[j]==INF)continue;
    //             // 2^{T[N-1]+i}-1+D[i]<=2^{T[N-1]+j}-1+D[j]
    //             if((1LL<<(T[N-1]+i))+D[i]>(1LL<<(T[N-1]+j))+D[j]){
    //                 ok=false;
    //                 break;
    //             }
    //         }
    //         if(ok){
    //             ll ans=power(2,T[N-1]+i)-1+D[i];
    //             ans%=MOD;
    //             if(ans<0)ans+=MOD;
    //             cout<<ans<<endl;
    //             break;
    //         }
    //     }
    // }
}
accuracy: 1
time_ms: 2440
memory_kb: 115412
final_rank: 15

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

namespace noya2 {

template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p){
    os << p.first << " " << p.second;
    return os;
}
template <typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &p){
    is >> p.first >> p.second;
    return is;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v){
    int s = (int)v.size();
    for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i];
    return os;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v){
    for (auto &x : v) is >> x;
    return is;
}

void in() {}
template <typename T, class... U>
void in(T &t, U &...u){
    cin >> t;
    in(u...);
}

void out() { cout << "\n"; }
template <typename T, class... U, char sep = ' '>
void out(const T &t, const U &...u){
    cout << t;
    if (sizeof...(u)) cout << sep;
    out(u...);
}

template<typename T>
void out(const vector<vector<T>> &vv){
    int s = (int)vv.size();
    for (int i = 0; i < s; i++) out(vv[i]);
}

struct IoSetup {
    IoSetup(){
        cin.tie(nullptr);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(15);
        cerr << fixed << setprecision(7);
    }
} iosetup_noya2;

const int iinf = 1'000'000'007;
const long long linf = 2'000'000'000'000'000'000LL;
const long long mod998 =  998244353;
const long long mod107 = 1000000007;
const long double pi = 3.14159265358979323;
const vector<int> dx = {0,1,0,-1,1,1,-1,-1};
const vector<int> dy = {1,0,-1,0,1,-1,-1,1};
const string ALP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string alp = "abcdefghijklmnopqrstuvwxyz";
const string NUM = "0123456789";

void yes(){ cout << "Yes\n"; }
void no(){ cout << "No\n"; }
void YES(){ cout << "YES\n"; }
void NO(){ cout << "NO\n"; }
void yn(bool t){ t ? yes() : no(); }
void YN(bool t){ t ? YES() : NO(); }


unsigned long long inner_binary_gcd(unsigned long long a, unsigned long long b){
    if (a == 0 || b == 0) return a + b;
    int n = __builtin_ctzll(a); a >>= n;
    int m = __builtin_ctzll(b); b >>= m;
    while (a != b) {
        int mm = __builtin_ctzll(a - b);
        bool f = a > b;
        unsigned long long c = f ? a : b;
        b = f ? b : a;
        a = (c - b) >> mm;
    }
    return a << min(n, m);
}

template<typename T> T gcd_fast(T a, T b){ return static_cast<T>(inner_binary_gcd(abs(a),abs(b))); }

long long sqrt_fast(long long n) {
    if (n <= 0) return 0;
    long long x = sqrt(n);
    while ((x + 1) * (x + 1) <= n) x++;
    while (x * x > n) x--;
    return x;
}

template<typename T> T floor_div(const T n, const T d) {
    assert(d != 0);
    return n / d - static_cast<T>((n ^ d) < 0 && n % d != 0);
}

template<typename T> T ceil_div(const T n, const T d) {
    assert(d != 0);
    return n / d + static_cast<T>((n ^ d) >= 0 && n % d != 0);
}

template<typename T> void uniq(vector<T> &v){
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
}

template <typename T, typename U> inline bool chmin(T &x, U y) { return (y < x) ? (x = y, true) : false; }

template <typename T, typename U> inline bool chmax(T &x, U y) { return (x < y) ? (x = y, true) : false; }

template<typename T> inline bool range(T l, T x, T r){ return l <= x && x < r; }

} // namespace noya2

#define rep(i,n) for (int i = 0; i < (int)(n); i++)
#define repp(i,m,n) for (int i = (m); i < (int)(n); i++)
#define reb(i,n) for (int i = (int)(n-1); i >= 0; i--)
#define all(v) (v).begin(),(v).end()

using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull = unsigned long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using pil = pair<int,ll>;
using pli = pair<ll,int>;

namespace noya2{

/*　~ (. _________ . /)　*/

}

using namespace noya2;

constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

void solve(int n, int p, int q){
    vector<vector<pil>> a(n), b(n);
    while (p--){
        int u, v; in(u,v); u--, v--;
        ll w; in(w);
        a[u].emplace_back(v,w);
        a[v].emplace_back(u,w);
    }
    while (q--){
        int u, v; in(u,v); u--, v--;
        ll w; in(w);
        b[u].emplace_back(v,w);
        b[v].emplace_back(u,w);
    }
    const int mx = 62;
    auto cmp = [&](pli x, pli y){
        auto [A, B] = x;
        auto [C, D] = y;
        if (A == linf) return false;
        if (C == linf) return true;
        A--;
        C--;
        // A+2^B < C+2^D
        if (B == D){
            return A < C;
        }
        else if (B < D){
            if (A - C <= 0) return true;
            if (B >= mx) return true;
            if (D - B >= mx) return true;
            ll lhs = ((A - C) >> B) + 1;
            ll rhs = (1LL << (D - B)) - 1;
            return lhs <= rhs;
        }
        else {
            if (C - A <= 0) return false;
            if (D >= mx) return false;
            if (B - D >= mx) return false;
            ll lhs = 1LL << (B - D);
            ll rhs = (C - A + (1LL << D) - 1) >> D;
            return lhs <= rhs;
        }
    };
    using dat = pair<pli,pii>;
    auto comp = [&](dat x, dat y){
        if (cmp(y.first,x.first)) return true;
        if (cmp(x.first,y.first)) return false;
        return x.second < y.second;
    };
    vector<vector<pli>> dist(mx,vector<pli>(n*2,{linf,70}));
    priority_queue<dat,vector<dat>, decltype(comp)> pque(comp);
    dist[0][0] = pli(0,0);
    pque.emplace(pli(0,0),pii(0,0));
    while (!pque.empty()){
        auto [d, iv] = pque.top(); pque.pop();
        auto [i, v] = iv;
        if (cmp(dist[i][v],d)) continue;
        if (v < n){
            for (auto [u, w] : a[v]){
                pli nd = d;
                nd.first += w;
                int ni = i;
                if (cmp(nd,dist[ni][u])){
                    dist[ni][u] = nd;
                    pque.emplace(dist[ni][u],pii(ni,u));
                }
            }
            for (auto [u, w] : b[v]){
                pli nd = d;
                nd.first += w;
                nd.second++;
                int ni = min(mx-1,i+1);
                int nu = n + u;
                if (cmp(nd,dist[ni][nu])){
                    dist[ni][nu] = nd;
                    pque.emplace(dist[ni][nu],pii(ni,nu));
                }
            }
        }
        else {
            for (auto [u, w] : a[v-n]){
                pli nd = d;
                nd.first += w;
                int ni = i;
                if (cmp(nd,dist[ni][u])){
                    dist[ni][u] = nd;
                    pque.emplace(dist[ni][u],pii(ni,u));
                }
            }
            for (auto [u, w] : b[v-n]){
                pli nd = d;
                nd.first += w;
                int ni = i;
                int nu = n + u;
                if (cmp(nd,dist[ni][nu])){
                    dist[ni][nu] = nd;
                    pque.emplace(dist[ni][nu],pii(ni,nu));
                }
            }
        }
    }
    pli cost(linf,70);
    rep(i,mx){
        if (cmp(dist[i][n-1],cost)){
            cost = dist[i][n-1];
        }
        if (cmp(dist[i][n+n-1],cost)){
            cost = dist[i][n+n-1];
        }
    }
    if (cost.first == linf){
        out(-1);
        return ;
    }
    ll ans = pow_mod_constexpr(2,cost.second,mod107) + cost.first + (mod107 - 1);
    ans %= mod107;
    out(ans);
}

int main(){
    while (true){
        int n, p, q; in(n,p,q);
        if (n == 0) break;
        solve(n,p,q);
    }
}
accuracy: 1
time_ms: 1730
memory_kb: 48084
final_rank: 8

code_snippet: #include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")

const int MOD = 998244353;
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
#define mid (l+(r-l)/2)

using ll = long long;
using ld = long double;
using str = string;
using i128 = __int128;

using pii = pair<int,int>;
using pll = pair<ll,ll>;
using pd = pair<ld,ld>;
#define f first
#define s second
#define cf cout<<flush

template <class T> using V = vector<T>;
using vi = V<int>;
using vvi = V<vi>;
using vl = V<ll>;
using vvl = V<vl>;
using vd = V<ld>;
using vpi = V<pii>;
using vpl = V<pll>;

#define sz(x) int((x).size())
#define bg(x) begin(x)
#define all(x) bg(x), end(x)
#define sor(x) sort(all(x))
#define sorr(x) sort(all(x)),reverse(all(x))
#define uniq(x) sor(x), x.resize(unique(all(x))-x.begin())
#define pb push_back
#define ft front()
#define bk back()
#define chmi(x,y, ...) x = min(__VA_OPT__({) x,y __VA_OPT__(,)__VA_ARGS__ __VA_OPT__(}))
#define chma(x,y, ...) x = max(__VA_OPT__({) x,y __VA_OPT__(,)__VA_ARGS__ __VA_OPT__(}))
#define lwb(x,y) (int)(lower_bound(all(x),y)-x.begin())
#define upb(x,y) (int)(upper_bound(all(x),y)-x.begin())
#define compress(v) {auto _t=v;uniq(_t);for(auto &x:v)x=lwb(_t,x);}
#define in(x,y,n,m) (x>=0&&x<n&&y>=0&&y<m)
#define retu(args, ...) {ps(args __VA_OPT__(,)__VA_ARGS__);return ;}

#define For(i,a,b) for(int i = (a); i <= (b); i++)
#define F0r(i,a) for(int i = 0; i < (a); i++)
#define Rof(i,a,b) for(int i = (b); i >= (a); i--)
#define R0f(i,a) for(int i = (a)-1; i >= 0; i--)
#define rep(a) F0r(_,a)
#define each(a,x) for(auto &a:x)

const int dx[4]{1,0,-1,0},dy[4]{0,1,0,-1};
const int dx8[8]{1,1,0,-1,-1,-1,0,1},dy8[8]{0,1,1,1,0,-1,-1,-1};
template <class T> using pqg = priority_queue<T,vector<T>,greater<T>>;

constexpr int pct(int x){return __builtin_popcount(x);}
constexpr int pctll(long long x){return __builtin_popcountll(x);}
constexpr int bits(int x){return 31-__builtin_clz(x);}

#define SFINAE(x, ...)                                                         \
    template <class, class = void> struct x : std::false_type {};              \
    template <class T> struct x<T, std::void_t<__VA_ARGS__>> : std::true_type {}

SFINAE(DefaultI, decltype(std::cin >> std::declval<T &>()));
SFINAE(DefaultO, decltype(std::cout << std::declval<T &>()));
SFINAE(IsTuple, typename std::tuple_size<T>::type);
SFINAE(Iterable, decltype(std::begin(std::declval<T>())));

template <auto &is> struct Reader {
    template <class T> void Impl(T &t) {
        if constexpr (DefaultI<T>::value) is >> t;
        else if constexpr (Iterable<T>::value) {
            for (auto &x : t) Impl(x);
        } else if constexpr (IsTuple<T>::value) {
            std::apply([this](auto &...args) { (Impl(args), ...); }, t);
        } else static_assert(IsTuple<T>::value, "No matching type for read");
    }
    template <class... Ts> void read(Ts &...ts) { ((Impl(ts)), ...); }
};

template <class... Ts> void re(Ts &...ts) { Reader<cin>{}.read(ts...); }
#define def(t, args...)                                                        \
    t args;                                                                    \
    re(args);

template <auto &os, bool debug, bool print_nd> struct Writer {
    string comma() const { return debug ? "," : ""; }
    template <class T> constexpr char Space(const T &) const {
        return print_nd && (Iterable<T>::value or IsTuple<T>::value) ? '\n'
                                                                     : ' ';
    }
    template <class T> void Impl(T const &t) const {
        if constexpr (DefaultO<T>::value) os << t;
        else if constexpr (Iterable<T>::value) {
            if (debug) os << '{';
            int i = 0;
            for (auto &&x : t)
                ((i++) ? (os << comma() << Space(x), Impl(x)) : Impl(x));
            if (debug) os << '}';
        } else if constexpr (IsTuple<T>::value) {
            if (debug) os << '(';
            std::apply(
                [this](auto const &...args) {
                    int i = 0;
                    (((i++) ? (os << comma() << " ", Impl(args)) : Impl(args)),
                     ...);
                },
                t);
            if (debug) os << ')';
        } else static_assert(IsTuple<T>::value, "No matching type for print");
    }
    template <class T> void ImplWrapper(T const &t) const {
        if (debug) os << "\033[0;31m";
        Impl(t);
        if (debug) os << "\033[0m";
    }
    template <class... Ts> void print(Ts const &...ts) const {
        ((Impl(ts)), ...);
    }
    template <class F, class... Ts>
    void print_with_sep(const std::string &sep, F const &f,
                        Ts const &...ts) const {
        ImplWrapper(f), ((os << sep, ImplWrapper(ts)), ...), os << '\n';
    }
    void print_with_sep(const std::string &) const { os << '\n'; }
};

template <class... Ts> void pr(Ts const &...ts) {
    Writer<cout, false, true>{}.print(ts...);
}
template <class... Ts> void ps(Ts const &...ts) {
    Writer<cout, false, true>{}.print_with_sep(" ", ts...);
}

void setIn(str s) { freopen(s.c_str(), "r", stdin); }
void setOut(str s) { freopen(s.c_str(), "w", stdout); }
void setIO(str s = "") {
    cin.tie(0)->sync_with_stdio(0);
    cout << fixed << setprecision(12);
    if (sz(s)) setIn(s + ".in"), setOut(s + ".out");
}

//#include<atcoder/all>
//using namespace atcoder;
#define N 200005

struct DSU{

    struct NODE{
        int p,sz;
        bool operator==(const NODE& o)const{
            return p==o.p;
        }
    };

    int _n;
    vector<NODE> node;

    DSU():DSU(0){}

    DSU(int n){
        _n=n;
        node.resize(n+1);
        for(int i=0;i<=n;i++){
            node[i]={i,1};
        }
    }

    int fp(int v){
        return v==node[v].p?v:node[v].p=fp(node[v].p);
    }

    void merge(int x,int y){
        x=fp(x),y=fp(y);
        if(x==y)return ;
        node[x].sz+=node[y].sz;
        node[y].p=x;
    }

    const NODE& operator[](int v){
        return node[fp(v)];
    }

};


void solve(){
    def(int,n,c,d);
    if(!n)exit(0);
    V<V<array<ll,3>>> g(n);
    DSU ds(n);
    rep(c){
        def(int,x,y,w);
        x--,y--;
        g[x].pb({y,w,0});
        g[y].pb({x,w,0});
        ds.merge(x,y);
    }
    rep(d){
        def(int,x,y,w);
        x--,y--;
        g[x].pb({y,w,1});
        g[y].pb({x,w,1});
        ds.merge(x,y);
    }
    if(ds[0]!=ds[n-1])retu(-1);
    // ps("ge");cf;
    V<vvl> dp(2,vvl(35,vl(n,1e18)));
    V<vpl> dpp(2,vpl(n,{1e18,1e18}));
    
    pqg<array<ll,4>> q;
    
    q.push({0,0,0,0});
    dp[0][0][0]=0;
    
    
    auto upd = [&](ll k,ll w,int st,int s) -> void {
        if(dp[st][k][s]>w){
            dp[st][k][s]=w;
            q.push({k,w,st,s});
        }
        
    };
    
    auto updd = [&](ll k,ll w,int st,int s) -> void {
        if(dpp[st][s]>pll{k,w}){
            dpp[st][s]={k,w};
            q.push({k,w,st,s});
        }
        
    };
    
    
    while(!q.empty()){
        auto [k,w,st,s]=q.top();
        q.pop();
        if(k>=35){
            if(dpp[st][s]>pll{k,w})continue;
            
            if(st){
                if(k<35)upd(k,w,0,s);
                else updd(k,w,0,s);
            }
            if(!st){
                if(k+1<35)upd(k+1,w,1,s);
                else updd(k+1,w,1,s);
            }
            
            for(auto &[x,xw,stt]:g[s]){
                if(st==stt){
                    updd(k,w+xw,st,x);
                }
            }
            
            continue;
        }
        if(dp[st][k][s]>w)continue;
        
        if(st){
            if(k<35)upd(k,w,0,s);
            else updd(k,w,0,s);
        }
        if(!st){
            if(k+1<35)upd(k+1,w,1,s);
            else updd(k+1,w,1,s);
        }
        
        for(auto &[x,xw,stt]:g[s]){
            if(st==stt){
                upd(k,w+xw,st,x);
                // dp[st][k][x]=w+xw;
                // q.push({k,w+xw,st,x});
            }
        }
        
    }
    
    ll ans=1e18,mod=1e9+7;
    
    F0r(i,35)chmi(ans,dp[0][i][n-1]+(1ll<<i)-1);
    
    if(ans!=1e18){
        ps(ans%mod);
    }
    else{
        ll now=1;
        rep(dpp[0][n-1].f)now=(now*2)%mod;
        ps((now-1+mod+dpp[0][n-1].s)%mod);   
    }
    
    
    return ;
}

int main(){
    setIO();
    int t=1;
    //re(t);
    while(true)solve();
    return 0;
}
accuracy: 1
time_ms: 1060
memory_kb: 24064
final_rank: 2

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

// スタンダードライブラリ
#include <bits/stdc++.h>
using namespace std;

// 多倍長整数
//  #if __has_include(<boost/multiprecision/cpp_int.hpp>)
//  #include <boost/multiprecision/cpp_int.hpp>
//  using lll =boost::multiprecision::int128_t;
//  #endif

// 型関連
using ll = long long;
using lint = long long;
using pll = pair<ll, ll>;
using plll = tuple<ll, ll, ll>;
using pii = pair<int, int>;
using piii = tuple<ll, ll, ll>;
template <class T> using prique = priority_queue<T>;

// 型定数
constexpr ll mod = 998244353;
constexpr ll MOD = 1000000007;
int inf = 2e9;
ll INF = 9e18;
#define endl '\n';

// 新規マクロ
#define all(a) (a).begin(), (a).end()
#define rep(i, N, limit) for (int i = (int)N; i < (int)limit; i++)

///////////////////// vector関連
template <class T, size_t n, size_t idx = 0>
auto make_vec(const size_t (&d)[n], const T &init) noexcept {
    if constexpr (idx < n)
        return std::vector(d[idx], make_vec<T, n, idx + 1>(d, init));
    else
        return init;
}

template <class T, size_t n> auto make_vec(const size_t (&d)[n]) noexcept {
    return make_vec(d, T{});
}

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

/////////////////////////// print関連
template <typename T> void print(vector<T> A);
void print();
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail);
void print(string S);
template <typename T> void print(vector<vector<T>> &F);

////////////////////////////
inline string input();
inline ll I();
inline pll II();

/////////////////////出力関連
inline void Yes(bool f);

bool solve() {
    int N, P, Q;
    cin >> N >> P >> Q;
    if (N == 0) {
        return false;
    }
    vector<vector<pll>> GP(N);
    vector<vector<pll>> GQ(N);
    for (int i = 0; i < P; i++) {
        ll a, b, c;
        cin >> a >> b >> c;
        a--;
        b--;
        GP[a].emplace_back(b, c);
        GP[b].emplace_back(a, c);
    }
    for (int i = 0; i < Q; i++) {
        ll a, b, c;
        cin >> a >> b >> c;
        a--;
        b--;
        GQ[a].emplace_back(b, c);
        GQ[b].emplace_back(a, c);
    }

    ll sh = 50;
    vector<ll> pow_2(1);
    pow_2[0] = 1;
    
    ll MOD = 1000000007;
    for (int i = 0; i < 20010; i++) {
        pow_2.push_back(pow_2[i] * 2LL);
        if (i >= sh) {
            pow_2.back()%=MOD;
        }
    }


    vector<vector<vector<ll>>> dist(
        2, vector<vector<ll>>(sh + 1, vector<ll>(N+1, INF)));
    vector<vector<vector<ll>>> f(
        2, vector<vector<ll>>(sh + 1, vector<ll>(N+1, 0)));
    prique<tuple<ll,ll,ll,ll>> que;

    que.emplace(0, 0, 0, 0);
    dist[0][0][0]=0;
    while (!que.empty()) {
        auto [d, v, k, o] = que.top();
        d=-d;
        que.pop();
        if (f[o][k][v]) {
            continue;
        }
        if (k == sh) {
            continue;
        }
        f[o][k][v] = true;
        for (auto [nv, w] : GP[v]) {
            if (dist[0][k][nv] > d + w) {
                dist[0][k][nv]=d+w;
                que.emplace(-d-w, nv,k,0);
            }
        }
        for (auto [nv, w] : GQ[v]) {
            ll cost = d + w, nk=k;
            if (o == 0) {
                cost += pow_2[k];
                nk++;
            }
            if (dist[1][nk][nv] > cost) {
                dist[1][nk][nv]=cost;
                que.emplace(-cost, nv, nk,1);
            }
        }
    }
    ll ans1 = INF;
    for (int i = 0; i <= sh; i++) {
        for (int j = 0; j < 2; j++) {
            ans1=min(ans1,dist[j][i][N-1]);
        }
    }
    if (ans1 != INF) {
        print(ans1 % MOD);
        return true;
    }

    //左側の方が小さいならtrueを返す
    auto hikaku = [&](ll k1, ll k2, ll d1, ll d2) {
        if (k1 == k2) {
            return d1<d2;
        }
        return k1<k2;
    };

    vector<vector<ll>> dist2(N, vector<ll>(2, INF));
    vector<vector<ll>> k_cnt(N,vector<ll>(2, INF));
    vector<vector<ll>> f2(N, vector<ll>(2, 0));
    prique<tuple<ll,ll,ll,ll>> que2;
    dist2[0][0] = 0;
    k_cnt[0][0]=0;
    que2.emplace(0,0, 0,0);
    while (!que2.empty()) {
        auto [k, d, v, o] = que2.top();
        que2.pop();
        k = -k;
        d = -d;
        if (f2[v][o]) {
            continue;
        }
        f2[v][o] = true;

        for (auto [nv, w] : GP[v]) {
            if (hikaku(k, k_cnt[nv][0], d+w, dist2[nv][0])) {
                dist2[nv][0] = d + w;
                k_cnt[nv][0] = k;
                que2.emplace(-k,-d-w, nv,0);
            }
        }
        for (auto [nv, w] : GQ[v]) {
            ll cost = d + w, nk=k;
            if (o == 0) {
                nk++;
            }
            if (hikaku(nk, k_cnt[nv][1], d + w, dist2[nv][1])) {
                dist2[nv][1] = d + w;
                k_cnt[nv][1] = nk;
                que2.emplace(-nk,-d-w, nv,1);
            }
        }
    }
    if (k_cnt[N - 1][0] == INF && k_cnt[N - 1][1] == INF) {
        print(-1);
        return true;
    }

    ll d1 = dist2[N - 1][0], d2 = dist2[N - 1][1];
    ll k1 = k_cnt[N - 1][0], k2 = k_cnt[N - 1][1];

    ll final_k=0, ans=0;
    if (hikaku(k1, k2, d1, d2)) {
        final_k = k1;
        ans=d1;
    } else {
        final_k = k2;
        ans=d2;
    }
    for (int i = 0; i < final_k; i++) {
        ans += pow_2[i];
        ans%=MOD;
    }
    print(ans);

    return true;
    





}

///////////////////ここから//////////////////////
int main() {
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    while (solve());
}

////////////////////print/////////////////////////
// 1次元ベクトルを出力する
template <typename T> void print(vector<T> A) {
    if (A.size() == 0) {
        return;
    }
    for (size_t i = 0; i < A.size() - 1; i++) {
        cout << A[i] << ' ';
    }
    cout << A[A.size() - 1] << endl;
    return;
}

// 2次元ベクトルを出力する
template <typename T> void print(vector<vector<T>> &F) {
    for (size_t i = 0; i < F.size(); i++) {
        for (size_t j = 0; j < F[i].size(); j++) {
            cout << F[i][j];
            if (j < F[i].size() - 1) {
                cout << ' ';
            }
        }
        cout << endl;
    }
}

// 空白行を出力するprint
void print() { cout << endl; }

// 数値・文字列を空白区切りで出力する. print(a,b)など
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    cout << head;
    if (sizeof...(tail) != 0)
        cout << " ";
    print(forward<Tail>(tail)...);
}

void print(string S) { cout << S << endl; }

/////////////////////初期化///////////////////////

inline string input() {
    string S;
    cin >> S;
    return S;
}
inline ll I() {
    ll ret;
    cin >> ret;
    return ret;
}
inline pll II() {
    pll ret;
    cin >> ret.first >> ret.second;
    return ret;
}

//////////////出力関連

inline void Yes(bool f) {
    if (f) {
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
}
accuracy: 1
time_ms: 1040
memory_kb: 46880
final_rank: 5

code_snippet: //#pragma GCC target("avx2")
//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using pli = pair<ll,int>;
//#define AMARI 998244353
#define AMARI 1000000007
#define el '\n'
#define El '\n'
#define YESNO(x) ((x) ? "Yes" : "No")
#define YES YESNO(true)
#define NO YESNO(false)
#define REV_PRIORITY_QUEUE(tp) priority_queue<tp,vector<tp>,greater<tp>>
#define EXIT_ANS(x) {cout << (x) << '\n'; return;}
template <typename T> void inline SORT(vector<T> &v){sort(v.begin(),v.end()); return;}
template <typename T> void inline VEC_UNIQ(vector<T> &v){sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); return;}
template <typename T> T inline MAX(vector<T> &v){return *max_element(v.begin(),v.end());}
template <typename T> T inline MIN(vector<T> &v){return *min_element(v.begin(),v.end());}
template <typename T> T inline SUM(vector<T> &v){T ans = 0; for(int i = 0; i < (int)v.size(); i++)ans += v[i]; return ans;}
template <typename T> void inline DEC(vector<T> &v){for(int i = 0; i < (int)v.size(); i++)v[i]--; return;}
template <typename T> void inline INC(vector<T> &v){for(int i = 0; i < (int)v.size(); i++)v[i]++; return;}
void inline TEST(void){cerr << "TEST" << endl; return;}
template <typename T> bool inline chmin(T &x,T y){
    if(x > y){
        x = y;
        return true;
    }
    return false;
}
template <typename T> bool inline chmax(T &x,T y){
    if(x < y){
        x = y;
        return true;
    }
    return false;
}
template <typename T = long long> vector<T> inline get_vec(int n){
    vector<T> ans(n);
    for(int i = 0; i < n; i++)cin >> ans[i];
    return ans;
}
template <typename T> void inline print_vec(vector<T> &vec,bool kaigyou = false){
    int n = (int)vec.size();
    for(int i = 0; i < n; i++){
        cout << vec[i];
        if(kaigyou || i == n - 1)cout << '\n';
        else cout << ' ';
    }
    if(!n)cout << '\n';
    return;
}
template <typename T> void inline debug_vec(vector<T> &vec,bool kaigyou = false){
    int n = (int)vec.size();
    for(int i = 0; i < n; i++){
        cerr << vec[i];
        if(kaigyou || i == n - 1)cerr << '\n';
        else cerr << ' ';
    }
    if(!n)cerr << '\n';
    return;
}
vector<vector<int>> inline get_graph(int n,int m = -1,bool direct = false){
    if(m == -1)m = n - 1;
    vector<vector<int>> g(n);
    while(m--){
        int u,v;
        cin >> u >> v;
        u--; v--;
        g[u].push_back(v);
        if(!direct)g[v].push_back(u);
    }
    return g;
}

vector<int> make_inv(vector<int> p){
    int n = (int)p.size();
    vector<int> ans(n);
    for(int i = 0; i < n; i++)ans[p[i]] = i;
    return ans;
}


#define IKITI 50

#define MULTI_TEST_CASE false
void solve(void){
    //問題を見たらまず「この問題設定から言えること」をいっぱい言う
    //よりシンプルな問題に言い換えられたら、言い換えた先の問題を自然言語ではっきりと書く
    //複数の解法のアイデアを思いついた時は全部メモしておく
    //g++ -D_GLIBCXX_DEBUG -Wall -O2 XXX.cpp -o o
    //N,P,Q <= 2e4
    int n;
    cin >> n;
    int p,q;
    cin >> p >> q;
    if(n == 0)exit(0);
    vector<vector<pli>> g(2 * n);
    while(p--){
        int u,v;
        ll w;
        cin >> u >> v >> w;
        u--; v--;
        g[u].push_back(pair(w,v));
        g[v].push_back(pair(w,u));
    }
    while(q--){
        int u,v;
        ll w;
        cin >> u >> v >> w;
        u--; v--;
        g[u + n].push_back(pair(w,v + n));
        g[v + n].push_back(pair(w,u + n));
    }
    //TEST();
    for(int i = 0; i < n; i++){
        g[i].push_back(pair(-1LL,i + n));
        g[i + n].push_back(pair(0LL,i));
    }

    n *= 2;
    //{time,taxi_cnt,idx}
    using tlll = tuple<ll,ll,ll>;
    priority_queue<tlll,vector<tlll>,greater<tlll>> que;
    que.push(tuple(0,0,0));

    vector<vector<ll>> dist(n,vector<ll>(IKITI + 1,LLONG_MAX / 2));
    vector<vector<bool>> seen(n,vector<bool>(IKITI + 1,false));
    dist[0][0] = 0LL;
    while(!que.empty()){
        ll time;
        int taxi_cnt,fr;
        tie(time,taxi_cnt,fr) = que.top(); que.pop();
        if(seen[fr][taxi_cnt])continue;
        seen[fr][taxi_cnt] = true;

        for(int i = 0; i < (int)g[fr].size(); i++){
            ll w;
            int to;
            tie(w,to) = g[fr][i];
            if(w == -1){
                if(taxi_cnt == IKITI)continue;
                if(chmin(dist[to][taxi_cnt + 1],dist[fr][taxi_cnt] + (1LL << taxi_cnt))){
                    que.push(tuple(time + (1LL << taxi_cnt),taxi_cnt + 1,to));
                }
                continue;
            }
            if(chmin(dist[to][taxi_cnt],dist[fr][taxi_cnt] + w)){
                que.push(tuple(time + w,taxi_cnt,to));
            }
        }
    }

    ll ans = LLONG_MAX;
    for(int i = 0; i <= IKITI; i++){
        //chmin(ans,dist[n - 1][i]);
        chmin(ans,dist[n / 2 - 1][i]);
    }
    if(ans != LLONG_MAX / 2){
        EXIT_ANS(ans % AMARI);
    }
    assert(que.empty());
    //{taxi_cnt,time,idx}
    que.push(tuple(0,0,0));
    vector<pair<int,ll>> dist2(n,pair(INT_MAX / 2,LLONG_MAX / 2));
    dist2[0] = pair(0,0LL);
    vector<bool> seen2(n);

    while(!que.empty()){
        int taxi_cnt,fr;
        ll time;
        tie(taxi_cnt,time,fr) = que.top(); que.pop();
        if(seen2[fr])continue;
        seen2[fr] = true;
        for(int i = 0; i < (int)g[fr].size(); i++){
            ll w; int to;
            tie(w,to) = g[fr][i];
            if(w == -1){
                pair<int,ll> temp;
                temp.first = taxi_cnt + 1;
                temp.second = time;
                if(chmin(dist2[to],temp)){
                    que.push(tuple(taxi_cnt + 1,time,to));
                }
                continue;
            }

            pair<int,ll> temp;
            temp.first = taxi_cnt;
            temp.second = time + w;
            if(chmin(dist2[to],temp)){
                que.push(tuple(taxi_cnt,time + w,to));
            }
        }
    }

    if(!seen2[n / 2 - 1]){
        EXIT_ANS(-1);
    }

    ans = dist2[n/2 - 1].second;
    ll ni = 1;
    for(int i = 0; i < dist2[n/2 - 1].first; i++){
        ni *= 2; ni %= AMARI;
    }
    ni--;
    ans += ni;
    ans %= AMARI;
    EXIT_ANS(ans);
}

void calc(void){
    return;
}


signed main(void){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    calc();
    int t = 1;
    if(MULTI_TEST_CASE)cin >> t;
    while(1){
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 2270
memory_kb: 38692
final_rank: 11

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

#define ALL(x) (x).begin(),(x).end()
#define IO ios::sync_with_stdio(false),cin.tie(nullptr);
#define REP(i, n) for(ll i=0; i<(ll)(n); i++)
#define FOR(i, a, b) for(ll i=(ll)(a); i<(b); i++)
#define ROF(i, a, b) for(ll i=(ll)(b)-1; i>=(a); i--)
#define rep(i, n) for (ll i = 0; i < (n); ++i)

template<typename T> int LB(const vector<T>& v, T x) { return lower_bound(ALL(v),x)-(v).begin(); }
template<typename T> int UQ(T& v) { sort(ALL(v)); v.erase(unique(ALL(v)),v.end()); return v.size(); }
template<typename T> bool chmax(T &a, T b) { return a<b ? a=b, true : false; }
template<typename T> bool chmin(T &a, T b) { return a>b ? a=b, true : false; }
template<typename T> using rpriority_queue=priority_queue<T,vector<T>,greater<T>>;
using ll=long long; const int INF=1e9+10; const ll INFL=4e18; using ld=long double;
using ull=unsigned long long; using lll=__int128_t; using VST=vector<string>;
using VI=vector<int>; using VVI=vector<VI>; using VL=vector<ll>; using VVL=vector<VL>;
using PL=pair<ll,ll>; using VP=vector<PL>; using WG=vector<vector<pair<int,ll>>>;

#ifdef LOCAL
#include "./debug.hpp"
#else
#define debug(...)
#define print_line
#endif



/// @brief ModInt
template<ll MOD>
struct ModInt {
    ModInt(ll x=0){ value=(x>=0?x%MOD:MOD-(-x)%MOD); }

    ModInt operator-() const { return ModInt(-value); }
    ModInt operator+() const { return ModInt(*this); }
    ModInt& operator+=(const ModInt& other) {
        value+=other.value;
        if(value>=MOD) value-=MOD;
        return*this;
    }
    ModInt& operator-=(const ModInt& other) {
        value+=MOD-other.value;
        if(value>=MOD) value-=MOD;
        return*this;
    }
    ModInt& operator*=(const ModInt other) {
        value=value*other.value%MOD;
        return*this;
    }
    ModInt& operator/=(ModInt other) {
        (*this)*=other.inv();
        return*this;
    }
    ModInt operator+(const ModInt& other) const { return ModInt(*this)+=other; }
    ModInt operator-(const ModInt& other) const { return ModInt(*this)-=other; }
    ModInt operator*(const ModInt& other) const { return ModInt(*this)*=other; }
    ModInt operator/(const ModInt& other) const { return ModInt(*this)/=other; }
    bool operator==(const ModInt& other) const { return value==other.value; }
    bool operator!=(const ModInt& other) const { return value!=other.value; }
    friend ostream& operator<<(ostream& os, const ModInt& x) { return os<<x.value; }
    friend istream& operator>>(istream& is, ModInt& x) {
        ll v;
        is>>v;
        x=ModInt<MOD>(v);
        return is;
    }

    ModInt pow(ll x) const { 
        ModInt ret(1),mul(value);
        while(x) {
            if(x&1) ret*=mul;
            mul*=mul;
            x>>=1;
        }
        return ret;
    }
    ModInt inv() const { return pow(MOD-2); }
    ll val() {return value; }
    static constexpr ll get_mod() { return MOD; }

private:
    ll value;
};

using Mod998=ModInt<998244353>;
using Mod107=ModInt<1000000007>;
using VM=vector<Mod998>;

using mint=Mod107;
//----------------------------------------------------------


bool solve() {
    ll N,P,Q; cin>>N>>P>>Q;
    if(N==0) return false;

    WG G(N),H(N);
    REP(i,P) {
        ll u,v,w; cin>>u>>v>>w; u--; v--;
        G[u].push_back({v,w});
        G[v].push_back({u,w});
    }
    REP(i,Q) {
        ll u,v,w; cin>>u>>v>>w; u--; v--;
        H[u].push_back({v,w});
        H[v].push_back({u,w});
    }

    {
        rpriority_queue<PL> pq;
        pq.push({0,0});
        VL dist(N,INF);
        dist[0]=0;
        while(!pq.empty()) {
            auto [d,now]=pq.top(); pq.pop();
            if(d>dist[now]) continue;
            debug(d,now);
            for(auto[a,b]:G[now]) if(chmin(dist[a],dist[now])) pq.push({dist[a],a});
            for(auto[a,b]:H[now]) if(chmin(dist[a],dist[now]+1)) pq.push({dist[a],a});
        }
        debug(dist);

        if(dist[N-1]==INF) {
            cout<<-1<<'\n';
            return true;
        }


        if(dist[N-1]>=51) {
            ll mx=dist[N-1];
            //タクシーに乗ってるか、載っていいないか
            rpriority_queue<tuple<ll,ll,ll,ll>> pq;
            pq.push({0,0,0,0});
            vector<VP> dp(N,VP(2,{INFL,INFL}));
            dp[0][0]={0,0};
            while(!pq.empty()) {
                auto [cnt,tmp,now,taxi]=pq.top(); pq.pop();
                if(dp[now][taxi]<PL{cnt,tmp}) continue;

                ll ncnt=taxi==1?cnt:cnt+1;

                //taxi H
                if(ncnt<=mx) {
                    for(auto [nxt,w]: H[now]) {
                        if(chmin(dp[nxt][1],{ncnt,dp[now][taxi].second+w})) {
                            pq.push({dp[nxt][1].first,dp[nxt][1].second,nxt,1});
                        }
                    }
                }
                //walk
                for(auto [nxt,w]: G[now]) {
                    if(chmin(dp[nxt][0],{cnt,dp[now][taxi].second+w})) {
                        pq.push({dp[nxt][0].first,dp[nxt][0].second,nxt,0});
                    }
                }
            }

            auto [cnt,dist]=min(dp[N-1][0],dp[N-1][1]);
            mint ans=mint(2).pow(cnt)-1;
            ans+=dist;
            cout<<ans<<'\n';
            return true;
        }
    }

    const int L=50;
    vector<VVL> dp(N,VVL(L+1,VL(2,INFL)));
    dp[0][0][0]=0;
    rpriority_queue<tuple<ll,ll,ll,ll>> pq;
    pq.push({0,0,0,0});

    while(!pq.empty()) {
        auto [tmp,now,cnt,taxi]=pq.top(); pq.pop();

        if(tmp>dp[now][cnt][taxi]) continue;

        debug(tmp,now,cnt,taxi);

        ll tak=taxi==1?0:1ll<<cnt;
        ll ncnt=taxi==1?cnt:cnt+1;

        //taxi H
        if(ncnt<=L) {
            for(auto [nxt,w]: H[now]) {
                if(chmin(dp[nxt][ncnt][1],dp[now][cnt][taxi]+w+tak)) {
                    pq.push({dp[nxt][ncnt][1],nxt,ncnt,1});
                }
            }
        }
        //walk
        for(auto [nxt,w]: G[now]) {
            if(chmin(dp[nxt][cnt][0],dp[now][cnt][taxi]+w)) {
                pq.push({dp[nxt][cnt][0],nxt,cnt,0});
            }
        }
    }

    ll ans=INFL;
    REP(i,L+1) REP(j,2) chmin(ans,dp[N-1][i][j]);

    if(ans==INFL) {
        cout<<-1<<'\n';
        return true;
    }

    ll mod=1e9+7;
    cout<<ans%mod<<'\n';

    return true;
}


int main() {
    IO;
    while(solve());
}
accuracy: 1
time_ms: 1720
memory_kb: 66592
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(...) std::begin(__VA_ARGS__), std::end(__VA_ARGS__)
#define rall(...) std::rbegin(__VA_ARGS__), std::rend(__VA_ARGS__)
#define OVERLOAD_REP(_1, _2, _3, _4, name, ...) name
#define REP1(n) for(ll i=0;i<n;i++)
#define REP2(i, n) for (ll i=0;i<n;i++)
#define REP3(i, a, n) for (ll i=a;i<n;i++)
#define REP4(i, a, b, n) for(ll i=a;i<n;i+=b)
#define rep(...) OVERLOAD_REP(__VA_ARGS__, REP4, REP3, REP2, REP1)(__VA_ARGS__)
#define OVERLOAD_RREP(_1, _2, _3, _4, name, ...) name
#define RREP1(n) for(ll i=n;i>=0;i--)
#define RREP2(i, n) for(ll i=n;i>=0;i--)
#define RREP3(i, a, n) for(ll i=n;i>=a;i--)
#define RREP4(i, a, b, n) for(ll i=n;i>=a;i-=b)
#define rrep(...) OVERLOAD_RREP(__VA_ARGS__, RREP4, RREP3, RREP2, RREP1)(__VA_ARGS__)
#define foa(a,v)  (auto& a : (v))
#define uniq(a) sort(all(a));a.erase(unique(all(a)),end(a))
#define len(n) (long long)(n).size()
#define pb push_back
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vs = vector<string>;
using vvs = vector<vs>;
using vvvs = vector<vvs>;
using vld = vector<ld>;
using vvld = vector<vld>;
using vvvld = vector<vvld>;
using vc = vector<char>;
using vvc = vector<vc>;
using vvvc = vector<vvc>;
using pll = pair<ll,ll>;
using vpll = vector<pll>;
using vvpll = vector<vpll>;
template<class... T>
constexpr auto min(T... a){
    return min(initializer_list<common_type_t<T...>>{a...});
}
template<class... T>
constexpr auto max(T... a){
    return max(initializer_list<common_type_t<T...>>{a...});
}
template<class... T>
void input(T&... a){
    (cin >> ... >> a);
}
ll modpow(ll a,ll b,ll c){
    ll ans = 1;
    while (b){
        if (b & 1){
            ans *= a;
            ans %= c;
        }
        a *= a;
        a %= c;
        b /= 2;
    }
    return ans;
}
#define INT(...) int __VA_ARGS__; input(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define STR(...) string __VA_ARGS__; input(__VA_ARGS__)
#define CHA(...) char __VA_ARGS__; input(__VA_ARGS__)
#define VLL(name,length) vll name(length);rep(i,length){cin >> name[i];}
#define VVLL(name,h,w) vvll name(h,vll(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVLL(name,a,b,c) vvvll name(a,vvll(b,vll(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VI(name,length) vi name(length);rep(i,length){cin >> name[i];}
#define VVI(name,h,w) vvi name(h,vi(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVI(name,a,b,c) vvvi name(a,vvll(b,vi(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VLD(name,length) vld name(length);rep(i,length){cin >> name[i];}
#define VVLD(name,h,w) vvld name(h,vld(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVLD(name,a,b,c) vvvld name(a,vvld(b,vld(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VC(name,length) vc name(length);rep(i,length){cin >> name[i];}
#define VVC(name,h,w) vvc name(h,vc(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVC(name,a,b,c) vvvc name(a,vvc(b,vc(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VS(name,length) vs name(length);rep(i,length){cin >> name[i];}
#define VVS(name,h,w) vvs name(h,vs(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVS(name,a,b,c) vvvs name(a,vvs(b,vs(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define PLL(name) pll name;cin>>name.first>>name.second;
#define VPLL(name,length) vpll name(length);rep(i,length){cin>>name[i].first>>name[i].second;}

void print(){cout << "\n";}
template<class T, class... Ts>
void print(const T& a, const Ts&... b){cout << a;(cout << ... << (cout << ' ', b));cout << '\n';}
void print(vll x){rep(i,len(x)){cout << x[i];if(i!=len(x)-1){cout << " ";}else{cout << '\n';}}}
void print(vvll x){rep(i,len(x))rep(j,len(x[i])){cout << x[i][j];if(j!=len(x[i])-1){cout << " ";}else{cout << '\n';}}}

using S = tuple<ll,ll,ll,ll>;

ll solve1(ll n,ll p,ll q,vvpll edge1,vvpll edge2){
    vvvll dist(n,vvll(40,vll(2,1LL<<60)));
    priority_queue<S,vector<S>,greater<S>> d;
    dist[0][0][0] = 0;
    d.push({0,0,0,0});
    while(!d.empty()){
        auto [z,now,cnt,s] = d.top();
        d.pop();
        if(z > dist[now][cnt][s]){continue;}
        if(s == 0){
            for(auto [to,cost]:edge1[now]){
                if(dist[to][cnt][s] > dist[now][cnt][s] + cost){
                    dist[to][cnt][s] = dist[now][cnt][s] + cost;
                    d.push({dist[to][cnt][s],to,cnt,s});
                }
            }
            if(cnt+1 < 40 && dist[now][cnt+1][s^1] > dist[now][cnt][s] + 0){
                dist[now][cnt+1][s^1] = dist[now][cnt][s] + 0;
                d.push({dist[now][cnt+1][s^1],now,cnt+1,s^1});
            }
        }
        else{
            for(auto [to,cost]:edge2[now]){
                if(dist[to][cnt][s] > dist[now][cnt][s] + cost){
                    dist[to][cnt][s] = dist[now][cnt][s] + cost;
                    d.push({dist[to][cnt][s],to,cnt,s});
                }
            }
            if(cnt+1 < 40 && dist[now][cnt][s^1] > dist[now][cnt][s] + 0){
                dist[now][cnt][s^1] = dist[now][cnt][s] + 0;
                d.push({dist[now][cnt][s^1],now,cnt,s^1});
            }
        }
        
        
    }
    ll ans = 1LL<<60;
    rep(i,40){
        ans = min(ans,min(dist[n-1][i][0],dist[n-1][i][1]) + (1LL<<i)-1);
        //print(i,min(dist[n-1][i][0],dist[n-1][i][1]));
    }
    return ans;
}
using F = tuple<ll,ll,ll>;
pll solve2(ll n,ll p,ll q,vvpll edge1,vvpll edge2){
    vvpll dist(n,vpll(2,{1LL<<60,1LL<<60}));
    priority_queue<S,vector<S>,greater<S>> d;
    dist[0][0] = {0,0};
    d.push({0,0,0,0});
    while(!d.empty()){
        auto [z,zz,now,s] = d.top();
        d.pop();
        if(make_pair(z,zz) > dist[now][s]){continue;}
        if(s == 0){
            for(auto [to,cost]:edge1[now]){
                if(dist[to][s] > make_pair(dist[now][s].first,dist[now][s].second + cost)){
                    dist[to][s] = make_pair(dist[now][s].first,dist[now][s].second + cost);
                    d.push({dist[to][s].first,dist[to][s].second,to,s});
                }
            }
            if(dist[now][s^1] > make_pair(dist[now][s].first + 1,dist[now][s].second)){
                dist[now][s^1] = make_pair(dist[now][s].first + 1,dist[now][s].second);
                d.push({dist[now][s^1].first,dist[now][s^1].second,now,s^1});
            }
        }
        else{
            for(auto [to,cost]:edge2[now]){
                if(dist[to][s] > make_pair(dist[now][s].first,dist[now][s].second + cost)){
                    dist[to][s] = make_pair(dist[now][s].first,dist[now][s].second + cost);
                    d.push({dist[to][s].first,dist[to][s].second,to,s});
                }
            }
            if(dist[now][s^1] > make_pair(dist[now][s].first,dist[now][s].second)){
                dist[now][s^1] = make_pair(dist[now][s].first,dist[now][s].second);
                d.push({dist[now][s^1].first,dist[now][s^1].second,now,s^1});
            }
        }
        
        
    }
    return min(dist[n-1][0],dist[n-1][1]);
}

int main(){
    while(1){
        LL(n,p,q);
        //if(n==4){break;}
        if(n == 0){break;}
        vvpll edge1(n);
        rep(i,p){
            LL(a,b,c);
            a--;
            b--;
            edge1[a].push_back({b,c});
            edge1[b].push_back({a,c});
        }
        vvpll edge2(n);
        rep(i,q){
            LL(a,b,c);
            a--;
            b--;
            edge2[a].push_back({b,c});
            edge2[b].push_back({a,c});
        }
        ll ans = solve1(n,p,q,edge1,edge2);
        if(ans != (1LL<<60)){
            print(ans % (1000000000 + 7));
            continue;
        }
        pll ans3 = solve2(n,p,q,edge1,edge2);
        if(ans3 == make_pair(1LL<<60,1LL<<60)){
            print(-1);
            continue;
        }
        else{
            ll ans2 = modpow(2,ans3.first,1000000000+7)-1 + ans3.second;
            ans2 %= 1000000000 + 7;
            print(ans2);
            continue;
        }

    }
}
accuracy: 1
time_ms: 1330
memory_kb: 84324
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<vvb> vvvb;
typedef vector<vvvb> vvvvb;
typedef pair<ll,ll> pi;
typedef pair<ll,pi> ppi;
typedef pair<ll,ppi> pppi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define RFOR(i,l,r) for(ll i=r-1;i>=l;i--)
#define RREP(i,n) RFOR(i,0,n)
#define sz(A) (ll)(A.size())
#define ALL(A) A.begin(),A.end()
#define LB(A,x) (ll)(lower_bound(ALL(A),x)-A.begin())
#define UB(A,x) (ll)(upper_bound(ALL(A),x)-A.begin())
#define COU(A,x) (UB(A,x)-LB(A,x))
#define F first
#define S second
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.F<<" "<<p.S;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.F>>p.S;return is;}
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){REP(i,sz(v))os<<v[i]<<(i+1!=sz(v)?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<class T>bool chmax(T&a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T>bool chmin(T&a,T b){if(b<a){a=b;return 1;}return 0;}
const ll mod=998244353;
template<const long long int mod=998244353>
struct modint{
  using mint=modint<mod>;
  long long int x;
  modint(long long int _x=0):x(_x%mod){if(x<0)x+=mod;}
  long long int val(){return x;}
  mint&operator=(const mint&a){x=a.x;return *this;}
  mint&operator+=(const mint&a){x+=a.x;if(x>=mod)x-=mod;return *this;}
  mint&operator-=(const mint&a){x-=a.x;if(x<0)x+=mod;return *this;}
  mint&operator*=(const mint&a){x*=a.x;x%=mod;return *this;}
  friend mint operator+(const mint&a,const mint&b){return mint(a)+=b;}
  friend mint operator-(const mint&a,const mint&b){return mint(a)-=b;}
  friend mint operator*(const mint&a,const mint&b){return mint(a)*=b;}
  mint operator-()const{return mint(0)-*this;}
  mint pow(long long int n){
    if(!n)return 1;
    mint a=1;
    mint _x=x;
    while(n){
      if(n&1)a*=_x;
      _x=_x*_x;n>>=1;
    }
    return a;
  }
  mint inv(){return pow(mod-2);}
  mint&operator/=(mint&a){return *this*=a.inv();}
  friend mint operator/(const mint&a,mint b){return mint(a)/=b;}
};
using mint=modint<998244353>;
int main(){
    while(1){
        ll N,_,__;cin>>N>>_>>__;
        if(!N)return 0;
        vector<vector<pi>>E(N),F(N);
        REP(i,_){
            ll a,b,c;cin>>a>>b>>c;a--;b--;
            E[a].emplace_back(b,c);
            E[b].emplace_back(a,c);
        }
        REP(i,__){
            ll a,b,c;cin>>a>>b>>c;a--;b--;
            F[a].emplace_back(b,c);
            F[b].emplace_back(a,c);
        }
        vvvi DP(2,vvi(60,vi(N,1e18)));
        DP[0][0][0]=0;
        min_priority_queue<pppi>Q;
        Q.emplace(pppi(0,ppi(0,pi(0,0))));
        while(sz(Q)){
            ll d=Q.top().F,tx=Q.top().S.F,c=Q.top().S.S.F,v=Q.top().S.S.S;Q.pop();
            if(d!=DP[tx][c][v])continue;
            if(tx){
                for(auto[u,x]:E[v])if(chmin(DP[0][c][u],d+x))Q.emplace(pppi(d+x,ppi(0,pi(c,u))));
                for(auto[u,x]:F[v])if(chmin(DP[1][c][u],d+x))Q.emplace(pppi(d+x,ppi(1,pi(c,u))));
            }
            else{
                for(auto[u,x]:E[v])if(chmin(DP[0][c][u],d+x))Q.emplace(pppi(d+x,ppi(0,pi(c,u))));
                for(auto[u,x]:F[v])if(c+1<60&&chmin(DP[1][c+1][u],d+x))Q.emplace(pppi(d+x,ppi(1,pi(c+1,u))));
            }
        }
        ll ans=8e18;
        REP(i,60){
            ll c=min(DP[0][i][N-1],DP[1][i][N-1]);
            chmin(ans,c+(1LL<<i)-1);
        }
        if(ans<1e17){
            cout<<ans%1000000007<<endl;
            continue;
        }
        {
            vector<vector<pi>>D(2,vector<pi>(N,pi(1e18,1e18)));
            D[0][0]=pi(0,0);
            min_priority_queue<pair<pi,pi>>Q;
            Q.emplace(D[0][0],pi(0,0));
            while(sz(Q)){
                ll tx=Q.top().S.F,v=Q.top().S.S;auto d=Q.top().F;Q.pop();
                if(d!=D[tx][v])continue;
                for(auto[u,x]:E[v])if(chmin(D[0][u],pi(d.F,d.S+x)))Q.emplace(D[0][u],pi(0,u));
                if(tx){
                    for(auto[u,x]:F[v])if(chmin(D[1][u],pi(d.F,d.S+x)))Q.emplace(D[1][u],pi(1,u));
                }
                else{
                    for(auto[u,x]:F[v])if(chmin(D[1][u],pi(d.F+1,d.S+x)))Q.emplace(D[1][u],pi(1,u));
                }
            }
            auto ans=min(D[0][N-1],D[1][N-1]);
            if(ans.F>1e17)cout<<-1<<endl;
            else{
                modint<1000000007>a=1;
                REP(i,ans.F)a*=2;
                a+=-1+ans.S;
                cout<<a.val()<<endl;
            }
        }
    }
    return 0;
}
accuracy: 1
time_ms: 1380
memory_kb: 34852
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

struct Edge {
    int To;
    ll Len;
    int Type;
};

int MAXS = 40;

typedef pair<ll,pair<int,pair<int,int>>> PP;
typedef pair<pair<int,ll>,pair<int,int>> PP2;

ll MOD = 1000000007;

ll Calc(int X) {
    if (X == 0) return 1;
    if (X % 2 == 0) {
        ll Y = Calc(X/2);
        return (Y*Y)%MOD;
    }
    return (2*Calc(X-1))%MOD;
}

int main() {
while(1) {
    int N, P, Q;
    cin >> N >> P >> Q;
    if (N == 0 && P == 0 && Q == 0) return 0;
    vector<vector<Edge>> G(N);
    rep(i,0,P) {
        int A, B;
        ll C;
        cin >> A >> B >> C;
        A--,B--;
        G[A].push_back({B,C,0});
        G[B].push_back({A,C,0});
    }
    rep(i,0,Q) {
        int A, B;
        ll C;
        cin >> A >> B >> C;
        A--, B--;
        G[A].push_back({B,C,1});
        G[B].push_back({A,C,1});
    }
    vector<vector<vector<ll>>> DP(N,vector<vector<ll>>(MAXS,vector<ll>(2,INF)));
    priority_queue<PP,vector<PP>,greater<PP>> PQ;
    DP[0][0][0] = 0;
    PQ.push({0,{0,{0,0}}});
    while(!PQ.empty()) {
        PP P = PQ.top();
        PQ.pop();
        ll Le = P.first;
        int Ve = P.second.first, Co = P.second.second.first, Ri = P.second.second.second;
        if (DP[Ve][Co][Ri]<Le) continue;
        for (Edge E : G[Ve]) {
            if (E.Type == 0 && Ri == 0) {
                ll NLe = Le + E.Len;
                int NVe = E.To, NCo = Co, NRi = Ri;
                if (DP[NVe][NCo][NRi] > NLe) {
                    DP[NVe][NCo][NRi] = NLe;
                    PQ.push({NLe,{NVe,{NCo,NRi}}});
                }
            }
            if (E.Type == 1 && Ri == 1) {
                ll NLe = Le + E.Len;
                int NVe = E.To, NCo = Co, NRi = Ri;
                if (DP[NVe][NCo][NRi] > NLe) {
                    DP[NVe][NCo][NRi] = NLe;
                    PQ.push({NLe,{NVe,{NCo,NRi}}});
                }
            }
            if (Ri == 0 && Co + 1 != MAXS) {
                ll NLe = Le + (1LL<<Co);
                int NVe = Ve, NCo = Co + 1, NRi = 1;
                if (DP[NVe][NCo][NRi] > NLe) {
                    DP[NVe][NCo][NRi] = NLe;
                    PQ.push({NLe,{NVe,{NCo,NRi}}});
                }
            }
            if (Ri == 1) {
                ll NLe = Le;
                int NVe = Ve, NCo = Co, NRi = 0;
                if (DP[NVe][NCo][NRi] > NLe) {
                    DP[NVe][NCo][NRi] = NLe;
                    PQ.push({NLe,{NVe,{NCo,NRi}}});
                }
            }
        }
    }
    ll ANS = INF;
    rep(i,0,MAXS) rep(j,0,2) chmin(ANS,DP[N-1][i][j]);
    if (ANS != INF) {
        cout << ANS%MOD << endl;
        continue;
    }
    vector<vector<pair<int,ll>>> DP2(N,vector<pair<int,ll>>(2,{inf,INF}));
    DP2[0][0] = {0,0};
    priority_queue<PP2,vector<PP2>,greater<PP2>> PQ2;
    PQ2.push({{0,0},{0,0}});
    while(!PQ2.empty()) {
        PP2 P = PQ2.top();
        PQ2.pop();
        int Co = P.first.first;
        ll Le = P.first.second;
        int Ve = P.second.first;
        int Ri = P.second.second;
        if (P.first > DP2[Ve][Ri]) continue;
        int NCo;
        ll NLe;
        int NVe;
        int NRi;
        if (Ri == 0) {
            NCo = Co + 1, NLe = Le, NVe = Ve, NRi = 1;
            if (DP2[NVe][NRi] > pair<int,ll>{NCo, NLe}) {
                DP2[NVe][NRi] = {NCo, NLe};
                PQ2.push({{NCo,NLe},{NVe,NRi}});
            }
        }
        if (Ri == 1) {
            NCo = Co, NLe = Le, NVe = Ve, NRi = 0;
            if (DP2[NVe][NRi] > pair<int,ll>{NCo, NLe}) {
                DP2[NVe][NRi] = {NCo, NLe};
                PQ2.push({{NCo,NLe},{NVe,NRi}});
            }
        }
        for (Edge E : G[Ve]) {
            if (E.Type == 0 && Ri == 0) {
                NCo = Co, NLe = Le + E.Len, NVe = E.To, NRi = 0;
                if (DP2[NVe][NRi] > pair<int,ll>{NCo, NLe}) {
                    DP2[NVe][NRi] = {NCo, NLe};
                    PQ2.push({{NCo,NLe},{NVe,NRi}});
                }
            }
            if (E.Type == 1 && Ri == 1) {
                NCo = Co, NLe = Le + E.Len, NVe = E.To, NRi = 1;
                if (DP2[NVe][NRi] > pair<int,ll>{NCo, NLe}) {
                    DP2[NVe][NRi] = {NCo, NLe};
                    PQ2.push({{NCo,NLe},{NVe,NRi}});
                }
            }
        }
    }
    pair<int,ll> ANS2 = min(DP2[N-1][0], DP2[N-1][1]);
    if (ANS2 == pair<int,ll>{inf,INF}) {
        cout << -1 << endl;
    }
    else {
        cout << (Calc(ANS2.first) + ANS2.second + MOD-1)%MOD << endl;
    }
}
}
accuracy: 1
time_ms: 2070
memory_kb: 62816
final_rank: 14

code_snippet: // (⁠◕⁠ᴗ⁠◕⁠✿⁠)
 
#include <bits/stdc++.h>
// #include <atcoder/all>
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define srep(i, s, n) for (ll i = s; i < (n); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
template<typename T> using vc = vector<T>;
template<typename T> using vv = vc<vc<T>>;
template<typename T> using vvv = vc<vv<T>>;
using vi = vc<int>;using vvi = vv<int>; using vvvi = vv<vi>;
using ll = long long;using vl = vc<ll>;using vvl = vv<ll>; using vvvl = vv<vl>;
using ld = long double; using vld = vc<ld>; using vvld = vc<vld>; using vvvld = vc<vvld>;
using uint = unsigned int;
using ull = unsigned long long;
const double pi = 3.141592653589793;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1000000007;
// const ll mod = 998244353;
inline bool inside(long long y, long long x, long long H, long long W) {return 0 <= (y) and (y) < (H) and 0 <= (x) and (x) < (W); }

#define debug(var)  do{std::cout << #var << " : \n";view(var);}while(0)
template<typename T> void view(T e){cout << e << endl;}
template<typename T> void view(const vc<T>& v){for(const auto& e : v){ cout << e << " "; } cout << endl;}
template<typename T> void view(const vv<T>& vv){ for(const auto& v : vv){ view(v); } }
template<typename T> void view(const set<T>& v){for(const auto& e : v){ cout << e << " "; } cout << endl;}


ll pow_mod(ll a, ll d, ll m){
    ll ret = 1;
    while (d > 0){
        if (d & 1){
            ret *= a;
            ret %= m;
        }
        a = a * a % m;
        d >>= 1;
    }
    return ret;
}


vl dijkstra(int s, int N, vv<pair<int, ll>> &g){
    using P = pair<ll, int>;
    vl dist(N, INF);
    priority_queue<P, vc<P>, greater<P>> q;
    dist[s] = 0;
    q.emplace(make_pair(0, s));
    while (!q.empty()){
        P tmp = q.top();q.pop();
        ll c = tmp.first; int now = tmp.second;
        if (dist[now] < c) continue;
        for (auto&& [nxt, nc]: g[now]){
            if (INF - nc > dist[now] && dist[nxt] > dist[now] + nc){
                dist[nxt] = dist[now] + nc;
                q.emplace(make_pair(dist[nxt], nxt));
            }
        }
    }
    return dist;
}

ll solve(int N, int p, int q){
    int taxi = 40;
    ll lim = 100100100100;
    vv<pair<int, ll>> g(N * taxi * 2);
    vv<pair<int, ll>> ng(N * 2);
    rep(i, p){
        int a, b; ll c; cin >> a >> b >> c; a--; b--;
        rep(t, taxi){
            g[a * taxi * 2 + t * 2].push_back({b * taxi * 2 + t * 2, c});
            g[b * taxi * 2 + t * 2].push_back({a * taxi * 2 + t * 2, c});
            ng[a * 2].push_back({b * 2, c});
            ng[b * 2].push_back({a * 2, c});
        }
    }
    rep(i, q){
        int d, e; ll f; cin >> d >> e >> f; d--; e--;
        rep(t, taxi){
            g[d * taxi * 2 + t * 2 + 1].push_back({e * taxi * 2 + t * 2 + 1, f});
            g[e * taxi * 2 + t * 2 + 1].push_back({d * taxi * 2 + t * 2 + 1, f});
            ng[d * 2 + 1].push_back({e * 2 + 1, f});
            ng[e * 2 + 1].push_back({d * 2 + 1, f});
        }
    }
    rep(u, N) rep(t, taxi - 1){
        g[u * taxi * 2 + t * 2].push_back({u * taxi * 2 + (t + 1) * 2 + 1, 1ll << t});
        g[u * taxi * 2 + (t + 1) * 2 + 1].push_back({u * taxi * 2 + (t + 1) * 2, 0});
    }
    auto dist = dijkstra(0, N * taxi * 2, g);

    ll ret = INF;
    rep(t, taxi) ret = min(ret, min(dist[(N - 1) * taxi * 2 + t * 2], dist[(N - 1) * taxi * 2 + t * 2 + 1]));
    if (ret == INF){
        rep(u, N){
            ng[u * 2].push_back({u * 2 + 1, lim});
            ng[u * 2 + 1].push_back({u * 2, 0});
        }
        auto ndist = dijkstra(0, 2 * N, ng);
        ll nw = ndist[(N - 1) * 2];
        if (nw == INF) ret = -1;
        else{
            ll cnt = nw / lim, dst = nw % lim;
            ret = (pow_mod(2, cnt, mod) - 1 + mod + dst) % mod;
        }
    }else ret %= mod;
    g.clear();
    g.shrink_to_fit();
    ng.clear();
    ng.shrink_to_fit();
    dist.clear();
    dist.shrink_to_fit();
    return ret;
}

int main(){
    vl ans;
    while (true){
        int N, p, q; cin >> N >> p >> q;
        if (N == 0) break;
        ans.push_back(solve(N, p, q));
    }
    for (auto x : ans) cout << x << endl;
}
accuracy: 1
time_ms: 3920
memory_kb: 252212
final_rank: 18

code_snippet: #if 1
// clang-format off
#include <bits/stdc++.h>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
using lf = long double;
using pll = pair<ll, ll>;
#define vec vector
template <class T> using v = vector<T>;
template <class T> using vv = v<v<T>>;
template <class T> using vvv = v<vv<T>>;
using vl = v<ll>;
using vvl = vv<ll>;
using vvvl = vvv<ll>;
using vpl = v<pll>;
using vs = v<string>;
using vb = v<bool>;
using vvb = v<vb>;
using vvvb = v<vvb>;
template<class T> using PQ = priority_queue<T, v<T>, greater<T>>;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }

#define FOR(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++)
#define rep(i, N) for (ll i = 0; i < (ll)(N); i++)
#define rep1(i, N) for (ll i = 1; i <= (ll)(N); i++)
#define rrep(i, N) for (ll i = N - 1; i >= 0; i--)
#define rrep1(i, N) for (ll i = N; i > 0; i--)
#define fore(i, a) for (auto &i : a)
#define fs first
#define sc second
#define eb emplace_back
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define UNIQUE(x) (x).erase(unique((x).begin(), (x).end()), (x).end());
#define YES(x) cout << ((x) ? "YES\n" : "NO\n");
#define Yes(x) cout << ((x) ? "Yes\n" : "No\n");
#define yes(x) cout << ((x) ? "yes\n" : "no\n");
template <class T, class U> void chmin(T &t, const U &u) { if (t > u) t = u; }
template <class T, class U> void chmax(T &t, const U &u) { if (t < u) t = u; }
template <class T> T min(const v<T> &lis) { return *min_element(all(lis)); }
template <class T> T max(v<T> &lis) { return *max_element(all(lis)); }
const int inf = (1 << 30);
const ll infl = (1LL << 60);
const ll mod93 = 998244353;
const ll mod17 = 1000000007;
int popcnt(uint x) { return __builtin_popcount(x); }
int popcnt(ull x) { return __builtin_popcountll(x); }
// 桁数
int bsr(uint x) { return 31 - __builtin_clz(x); }
int bsr(ull x) { return 63 - __builtin_clzll(x); }
// 2で割れる回数
int bsf(uint x) { return __builtin_ctz(x); }
int bsf(ull x) { return __builtin_ctzll(x); }

template <class T, class S> istream &operator>>(istream &is, pair<T, S> &x) { return is >> x.first >> x.second; }
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &x) { return os << x.first << " " << x.second; }
template <class T> istream &operator>>(istream &is, vector<T> &x) { for (auto &y : x) is >> y; return is; }
template <class T> ostream &operator<<(ostream &os, const vector<T> &x) {
  for (size_t i = 0, size = x.size(); i < size; i++)
    os << x[i] << (i == size - 1 ? "" : " ");
  return os;
}

ll rand_int(ll l, ll r) {  // [l, r]
  static random_device rd;
  static mt19937 gen(rd());
  return uniform_int_distribution<ll>(l, r)(gen);
}

// #include <boost/multiprecision/cpp_int.hpp>
// using cpp_int = boost::multiprecision::cpp_int;

// clang-format on
#endif

// #define _GLIBCXX_DEBUG
namespace atcoder {

  namespace internal {

    // @param m `1 <= m`
    // @return x mod m
    constexpr long long safe_mod(long long x, long long m) {
      x %= m;
      if (x < 0) x += m;
      return x;
    }

    // Fast modular multiplication by barrett reduction
    // Reference: https://en.wikipedia.org/wiki/Barrett_reduction
    // NOTE: reconsider after Ice Lake
    struct barrett {
      unsigned int _m;
      unsigned long long im;

      // @param m `1 <= m < 2^31`
      barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

      // @return m
      unsigned int umod() const { return _m; }

      // @param a `0 <= a < m`
      // @param b `0 <= b < m`
      // @return `a * b % m`
      unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1)
        // < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
      }
    };

    // @param n `0 <= n`
    // @param m `1 <= m`
    // @return `(x ** n) % m`
    constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
      if (m == 1) return 0;
      unsigned int _m = (unsigned int)(m);
      unsigned long long r = 1;
      unsigned long long y = safe_mod(x, m);
      while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
      }
      return r;
    }

    // Reference:
    // M. Forisek and J. Jancina,
    // Fast Primality Testing for Integers That Fit into a Machine Word
    // @param n `0 <= n`
    constexpr bool is_prime_constexpr(int n) {
      if (n <= 1) return false;
      if (n == 2 || n == 7 || n == 61) return true;
      if (n % 2 == 0) return false;
      long long d = n - 1;
      while (d % 2 == 0) d /= 2;
      constexpr long long bases[3] = {2, 7, 61};
      for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
          y = y * y % n;
          t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
          return false;
        }
      }
      return true;
    }
    template <int n> constexpr bool is_prime = is_prime_constexpr(n);

    // @param b `1 <= b`
    // @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
    constexpr std::pair<long long, long long> inv_gcd(
        long long a, long long b) {
      a = safe_mod(a, b);
      if (a == 0) return {b, 0};

      // Contracts:
      // [1] s - m0 * a = 0 (mod b)
      // [2] t - m1 * a = 0 (mod b)
      // [3] s * |m1| + t * |m0| <= b
      long long s = b, t = a;
      long long m0 = 0, m1 = 1;

      while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
      }
      // by [3]: |m0| <= b/g
      // by g != b: |m0| < b/g
      if (m0 < 0) m0 += b / s;
      return {s, m0};
    }

    // Compile time primitive root
    // @param m must be prime
    // @return primitive root (and minimum in now)
    constexpr int primitive_root_constexpr(int m) {
      if (m == 2) return 1;
      if (m == 167772161) return 3;
      if (m == 469762049) return 3;
      if (m == 754974721) return 11;
      if (m == 998244353) return 3;
      int divs[20] = {};
      divs[0] = 2;
      int cnt = 1;
      int x = (m - 1) / 2;
      while (x % 2 == 0) x /= 2;
      for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
          divs[cnt++] = i;
          while (x % i == 0) {
            x /= i;
          }
        }
      }
      if (x > 1) {
        divs[cnt++] = x;
      }
      for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
          if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
            ok = false;
            break;
          }
        }
        if (ok) return g;
      }
    }
    template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

  }  // namespace internal

  long long pow_mod(long long x, long long n, int m) {
    assert(0 <= n && 1 <= m);
    if (m == 1) return 0;
    internal::barrett bt((unsigned int)(m));
    unsigned int r = 1, y = (unsigned int)(internal::safe_mod(x, m));
    while (n) {
      if (n & 1) r = bt.mul(r, y);
      y = bt.mul(y, y);
      n >>= 1;
    }
    return r;
  }
}  // namespace atcoder
using namespace atcoder;

ll m = 50;
struct S {
  pll cost;
  ll now, cnt, cur;
};
bool operator<(S a, S b) {
  if (a.cost.fs == b.cost.fs || max(a.cost.fs, b.cost.fs) >= m) {
    return a.cost < b.cost;
  }
  ll ac = a.cost.sc + (1ll << a.cost.fs) - 1;
  ll bc = b.cost.sc + (1ll << b.cost.fs) - 1;
  return ac < bc;
}
bool operator>(S a, S b) {
  if (a.cost.fs == b.cost.fs || max(a.cost.fs, b.cost.fs) >= m) {
    return a.cost > b.cost;
  }
  ll ac = a.cost.sc + (1ll << a.cost.fs) - 1;
  ll bc = b.cost.sc + (1ll << b.cost.fs) - 1;
  return ac > bc;
}
struct Solver {
  void solve(ll n, ll p, ll q) {
    using tup = tuple<ll, ll, ll>;
    vv<tup> g(n);
    rep(i, p) {
      ll a, b, c;
      cin >> a >> b >> c;
      a--, b--;
      g[a].eb(b, c, 0);
      g[b].eb(a, c, 0);
    }
    rep(i, q) {
      ll a, b, c;
      cin >> a >> b >> c;
      a--, b--;
      g[a].eb(b, c, 1);
      g[b].eb(a, c, 1);
    }

    vv<vpl> dp(n, v<vpl>(m + 1, vpl(2, {infl, infl})));
    dp[0][0][0] = {0, 0};
    v<vvb> used(n, vvb(m + 1, vb(2)));
    PQ<S> pq;
    pq.push({
        {0, 0},
        0, 0, 0
    });
    while (pq.size()) {
      ll now = pq.top().now;
      ll cnt = pq.top().cnt;
      ll cur = pq.top().cur;
      if (cnt > m) cnt = m;
      pq.pop();
      // cout << now << " " << cnt << "\n";
      ll cnt_i = min(cnt, m);
      if (used[now][cnt_i][cur]) continue;
      used[now][cnt_i][cur] = true;

      for (auto [to, c1, c2] : g[now]) {
        pll tmp = dp[now][cnt_i][cur];
        if (cur == 0) tmp.fs += c2;
        tmp.sc += c1;
        if (tmp < dp[to][min(tmp.fs, m)][c2]) {
          dp[to][min(tmp.fs, m)][c2] = tmp;
          pq.push({tmp, to, min(tmp.fs, m), c2});
        }
      }
    }
    // rep(i, n) {
    //   rep(j, m + 1) { cout << "(" << dp[i][j] << ")" << " \n"[j == m]; }
    // }
    pll ans = {infl, infl};
    rep(i, m + 1) {
      rep(j, 2) {
        pll tmp = dp[n - 1][i][j];
        if (tmp.fs == ans.fs || max(tmp.fs, ans.fs) >= m) {
          chmin(ans, tmp);
        } else {
          ll tc = tmp.sc + (1ll << tmp.fs) - 1;
          ll ac = ans.sc + (1ll << ans.fs) - 1;
          if (tc < ac) ans = tmp;
        }
      }
    }
    // cout << ans << "\n";
    if (ans == pll{infl, infl}) {
      cout << -1 << "\n";
      return;
    }
    ll MOD = TEN(9) + 7;
    ll out = pow_mod(2, ans.fs, MOD) - 1 + ans.sc;
    out %= MOD;
    cout << out << "\n";
  }
};

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(20);

  ll t = 1;
  // cin >> t;
  while (t) {
    ll n, p, q;
    cin >> n >> p >> q;
    if (n == 0) break;

    Solver solver;
    solver.solve(n, p, q);
    // break;
  }
}
accuracy: 1
time_ms: 4140
memory_kb: 155280
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (long long i = 0; i < (long long)(n); i++)
#define rrep(i,start,end) for (long long i = start;i >= (long long)(end);i--)
#define repn(i,end) for(long long i = 0; i <= (long long)(end); i++)
#define reps(i,start,end) for(long long i = start; i < (long long)(end); i++)
#define repsn(i,start,end) for(long long i = start; i <= (long long)(end); i++)
#define each(p,a) for(auto &p:a)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<long long> vll;
typedef vector<pair<long long ,long long>> vpll;
typedef vector<vector<long long>> vvll;
typedef set<ll> sll;
typedef map<long long , long long> mpll;
typedef pair<long long ,long long> pll;
typedef tuple<long long , long long , long long> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (int)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1LL << 60;
const ld EPS = 1e-9;
 
inline ll lfloor(ll x,ll m){return (x - ((x % m+ m)%m))/m;}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

// for AOJ or ICPC or etc..
// 全部が0だったらtrueを返す
template<class Tp> bool zero (const Tp &x) {return x == 0;}
template<class Tp, class... Args> bool zero (const Tp &x, const Args& ...args) {return zero(x) and zero(args...);}


ll modpow(ll a, ll n){
    ll ans = 1, cur = a;
    while (n > 0){
        if (n & 1) ans = ans * cur % MOD10;
        cur = cur * cur % MOD10;
        n >>= 1;
    }
    return ans;
}
// 変数をちゃんと全部受け取る！
void solve(ll n,ll P, ll Q){
  vector<vpll> h(n),r(n);
  rep(i,P){
    LL(a,b,c);
    a--;b--;
    h[a].push_back({b,c});
    h[b].push_back({a,c});
  }
  rep(i,Q){
    LL(d,e,f);
    d--;e--;
    r[d].push_back({e,f});
    r[e].push_back({d,f});
  }
  ll kcnt = 0;
  {
    deque<ll> que;
    //0からの距離が入る
    vector<ll> find(2 * n,INF);
    find[0] = 0;
    que.push_back(0);
    while(!que.empty()){
      ll now = que.front();
      que.pop_front();
      for(auto &[p,tmp]:h[now % n]){
        if(find[p] > find[now]){
          find[p] = find[now];
          que.push_front(p);
        }
      }
      for(auto &[p,tmp]:r[now % n]){
        if(find[p+n]  > find[now] + (ll)(now < n)){
          find[p+n] = find[now] + (ll)(now < n);
          if(now < n){
            que.push_back(p+n);  
          }else{
            que.push_front(p+n);
          }
        }
      }
    }
    if(find[n-1] == INF && find[2 * n-1] == INF){
      cout << -1 << endl;
      return ;
    }else{
      kcnt = min(find[n-1],find[2 * n-1]);
    }
  }
  // cerr << kcnt << endl;
  if(kcnt >= 40){
    //kcnt回だけ乗るのが最適
    //乗ってる乗ってないの頂点倍化だけして{乗った回数,移動時間}でダイクストラ
    using P = pair<pair<ll,ll>,ll> ;
    vpll dis(2 * n,{INF,INF});//i<n: 降りてる i>=n: 乗ってる
    dis[0] = {0,0};
    priority_queue<P,vector<P>,greater<P>> pq;
    pq.push((P){dis[0],0});
    while(!pq.empty()){
      auto [np,now] = pq.top();
      pq.pop();
      if(dis[now] < np){
        continue;
      }
      auto [cnt,cost] = np;
      for(auto &p:h[now % n]){
        auto[next,hcost] = p;
        if(dis[next] > (pll){cnt,cost + hcost}){
          dis[next] = (pll){cnt,cost + hcost};
          pq.push({(pll){cnt,cost + hcost},next});
        }
      }
      for(auto &p:r[now % n]){
        auto[next,rcost] = p;
        if(dis[next+n] > (pll){cnt +(ll)(now < n),cost + rcost}){
          dis[next+n] = (pll){cnt +(ll)(now < n),cost + rcost};
          pq.push({(pll){cnt+(ll)(now < n),cost + rcost},next+n});
        }
      }
    }
    if(dis[n-1] < dis[2 * n-1]){
      // cerr << kcnt << " " << dis[n-1].first << endl;
      assert(dis[n-1].first == kcnt);
      ll ans = modpow(2,dis[n-1].first) -1;
      ans += dis[n-1].second;
      ans %= MOD10;
      cout << ans << endl;
    }else{
      assert(dis[2 * n-1].first == kcnt);
      ll ans = modpow(2,dis[2 *n-1].first) -1;
      ans += dis[2*n-1].second;
      ans %= MOD10;
      cout << ans << endl;
    }
  }else{
    //頂点倍化ダイクストラ
    // G[i]<j,d> i->j の距離(d)
    // 「仮の最短距離, 頂点」が小さい順に並ぶ
    vll dis(80 * n,INF);//[0,39]: i回乗って降りている [40,79] i-40回乗って乗っている
    priority_queue<pll,vector<pll>,greater<pll>>pq;
    dis[0] = 0;
    pq.push({dis[0],0});
    while(!pq.empty()){
      auto [len,now] = pq.top();
      pq.pop();
      if(dis[now]< len){
        continue;
      }
      for(auto &p:h[now % n]){
        // 注意！
        auto [next,cost] = p;
        ll times = now/ n;
        if(times >= 40){
          times -= 40;
        }
        next += n * times;
        if(dis[next] > dis[now] + cost){
          dis[next] = dis[now] + cost;
          pq.push({dis[next],next});
        }
      }
      for(auto &p:r[now % n]){
        // 注意！
        auto [next,cost] = p;
        ll times = now/ n;
        ll ncost = dis[now] + cost;
        if(times >= 40){
          //乗ってるので乗ったまま
          next += times * n;
        }else{
          //降りてるので次のに乗る
          if(times == 39){
            //乗る意味ないのでパス
            continue;
          }else{
            ncost += (1LL << times);
            times++;//次の
            times += 40;//乗る
            next += times * n;
          }
        }
        if(dis[next] > ncost){
          dis[next] = ncost;
          pq.push({dis[next],next});
        }
      }
    }

    ll ans = INF;
    rep(i,40){
      chmin(ans,dis[(i+1) * n-1]);
      chmin(ans,dis[(i+1+40) * n -1]);
    }
    cout << ans % MOD10 << endl;
  }
}
 
int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  while(true){
    LL(n,P,Q);//変数数調整
    if(zero(n,P,Q))break;
    solve(n,P,Q);
  }
}
accuracy: 1
time_ms: 790
memory_kb: 20740
final_rank: 1