#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

const int MAXN = 100100;

struct edge {
    int to, time;

    bool operator < ( const edge & p ) const {
        if ( time < p.time ) return 1;
        return 0;
    }

    edge ( int to_ = 0, int time_ = 0 ) {
        to = to_;
        time = time_;
    }

};

int n, m;
vector < edge > v[MAXN];
vector < int > arr[MAXN];
priority_queue < edge > q;
int lv[MAXN];
unsigned int d[MAXN];

void read() {
    int i, j, x, y, z, k;

    scanf ( "%d %d", &n, &m );

    for ( i = 0; i < m; ++ i ) {
        scanf ( "%d %d %d", &x, &y, &z );
lv[x] ++;
lv[y] ++;
        v[x].push_back ( edge ( y, z ) );
        v[y].push_back ( edge ( x, z ) );
    }

    for ( i = 1; i <= n; ++ i ) {
        scanf ( "%d", &k );

        for ( j = 0; j < k; ++ j ) {
            scanf ( "%d", &x );
            arr[i].push_back ( x );
        }
    }

}

int find_next_time ( int idx, int ll, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid, best;
    best = r;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( num - arr[idx][mid] - num <= mid - ll ) {
            l = mid + 1;
        }
        else if ( num - arr[idx][mid] > mid - ll ) {
            r = mid - 1;
            best = r;
        }

    }
//printf ( "%d %d\n", best, arr[idx][best] + 1 );
    return arr[idx][best] + 1;

}

int find_time ( int idx, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid;

    if ( r == ( int ) arr[idx].size() ) return num;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( arr[idx][mid] == num ) {
            return find_next_time ( idx, mid, num );
        }

        if ( arr[idx][mid] < num ) {
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }

    }

    return num;

}

void solve ( int start, int end ) {
    int i;
    edge tc;

    memset ( d, 0 - 1, sizeof d );

    int cur = find_time ( start, 0 );

    d[start] = cur;
//printf ( "%d\n", cur );
    q.push ( edge ( start, cur ) );

    while ( !q.empty () ) {
        tc = q.top(), q.pop();
if ( !lv [ tc.to] ) continue;
        if ( tc.time <= d[tc.to] ) {
            int sz = ( int ) v[tc.to].size();
            int cur = find_time ( tc.to, tc.time );
            cur -= tc.time;

            for ( i = 0; i < sz; ++ i ) {
                //if ( tc.to == 2 ) printf ( "%d %d\n", v[tc.to][i].to, tc.time + v[tc.to][i].time + cur );
                //printf ( "%d %d %d\n", tc.to, tc.time, cur );
                if ( d[ v[tc.to][i].to ] > tc.time + v[tc.to][i].time + cur && lv[ v[tc.to][i].to ]) {
                    d[ v[tc.to][i].to ] = v[tc.to][i].time + tc.time + cur;
lv[ v[tc.to][i].to ] --;
lv[ tc.to ] --;
                    q.push ( edge ( v[tc.to][i].to, d[ v[tc.to][i].to ] ) );
                }
            }
        }
    }

    if ( d[end] == ( unsigned int ) ( 0 - 1 ) ) printf ( "-1\n" );
    else printf ( "%d\n", d[end] );

}

int main() {
    read();
    solve ( 1, n );

    return 0;

}


#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

const int MAXN = 100100;

struct edge {
    int to, time;

    bool operator < ( const edge & p ) const {
        if ( time < p.time ) return 1;
        return 0;
    }

    edge ( int to_ = 0, int time_ = 0 ) {
        to = to_;
        time = time_;
    }

};

int n, m;
vector < edge > v[MAXN];
vector < int > arr[MAXN];
unsigned int d[MAXN];

void read() {
    int i, j, x, y, z, k;

    scanf ( "%d %d", &n, &m );

    for ( i = 0; i < m; ++ i ) {
        scanf ( "%d %d %d", &x, &y, &z );

        v[x].push_back ( edge ( y, z ) );
        v[y].push_back ( edge ( x, z ) );
    }

    for ( i = 1; i <= n; ++ i ) {
        scanf ( "%d", &k );

        for ( j = 0; j < k; ++ j ) {
            scanf ( "%d", &x );
            arr[i].push_back ( x );
        }
    }

}

int find_next_time ( int idx, int ll, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid, best;
    best = r;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( num - arr[idx][mid] - num <= mid - ll ) {
            l = mid + 1;
        }
        else if ( num - arr[idx][mid] > mid - ll ) {
            r = mid - 1;
            best = r;
        }

    }

    return arr[idx][best] + 1;

}

int find_time ( int idx, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid;

    if ( r == ( int ) arr[idx].size() ) return num;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( arr[idx][mid] == num ) {
            return find_next_time ( idx, mid, num );
        }

        if ( arr[idx][mid] < num ) {
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }

    }

    return num;

}

void solve ( int start, int end ) {
    int i;
    edge tc;

    priority_queue < edge > q;

    memset ( d, ( 0 - 1 ), sizeof d );

    int cur = find_time ( start, 0 );

    d[start] = cur;

    q.push ( edge ( start, cur ) );

    while ( !q.empty () ) {
        tc = q.top();
        q.pop();

        if ( tc.time <= d[tc.to] ) {
            int sz = ( int ) v[tc.to].size();
            int cur = find_time ( tc.to, tc.time );
            cur -= tc.time;

            for ( i = 0; i < sz; ++ i ) {
                if ( d[ v[tc.to][i].to ] > tc.time + v[tc.to][i].time + cur ) {
                    d[ v[tc.to][i].to ] = v[tc.to][i].time + tc.time + cur;
                    q.push ( edge ( v[tc.to][i].to, d[ v[tc.to][i].to ] ) );
                }
            }
        }
    }

    if ( d[end] == ( unsigned int ) ( 0 - 1 ) ) printf ( "-1\n" );
    else printf ( "%d\n", d[end] );

}

int main() {
    read();
    solve ( 1, n );

    return 0;

}


#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

const int MAXN = 100100;

struct edge {
    int to, time;

    bool operator < ( const edge & p ) const {
        if ( time > p.time ) return 1;
        return 0;
    }

    edge ( int to_ = 0, int time_ = 0 ) {
        to = to_;
        time = time_;
    }

};

int n, m;
vector < edge > v[MAXN];
vector < int > arr[MAXN];
unsigned int d[MAXN];

void read() {
    int i, j, x, y, z, k;

    scanf ( "%d %d", &n, &m );

    for ( i = 0; i < m; ++ i ) {
        scanf ( "%d %d %d", &x, &y, &z );

        v[x].push_back ( edge ( y, z ) );
        v[y].push_back ( edge ( x, z ) );
    }

    for ( i = 1; i <= n; ++ i ) {
        scanf ( "%d", &k );

        for ( j = 0; j < k; ++ j ) {
            scanf ( "%d", &x );
            arr[i].push_back ( x );
        }
    }

}

int find_next_time ( int idx, int ll, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid, best;
    best = r;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( num - arr[idx][mid] - num <= mid - ll ) {
            l = mid + 1;
        }
        else if ( num - arr[idx][mid] > mid - ll ) {
            r = mid - 1;
            best = r;
        }

    }

    return arr[idx][best] + 1;

}

int find_time ( int idx, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid;

    if ( r == ( int ) arr[idx].size() ) return num;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( arr[idx][mid] == num ) {
            return find_next_time ( idx, mid, num );
        }

        if ( arr[idx][mid] < num ) {
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }

    }

    return num;

}

void solve ( int start, int end ) {
    int i;
    edge tc;

    priority_queue < edge > q;

    memset ( d, ( 0 - 1 ), sizeof d );

    int cur = find_time ( start, 0 );

    d[start] = cur;

    q.push ( edge ( start, cur ) );

    while ( !q.empty () ) {
        tc = q.top();
        q.pop();

        if ( tc.time <= d[tc.to] ) {
            int sz = ( int ) v[tc.to].size();
            int cur = find_time ( tc.to, tc.time );
            cur -= tc.time;

            for ( i = 0; i < sz; ++ i ) {
                if ( d[ v[tc.to][i].to ] > tc.time + v[tc.to][i].time + cur ) {
                    d[ v[tc.to][i].to ] = v[tc.to][i].time + tc.time + cur;
                    q.push ( edge ( v[tc.to][i].to, d[ v[tc.to][i].to ] ) );
                }
            }
        }
    }

    if ( d[end] == ( unsigned int ) ( 0 - 1 ) ) printf ( "-1\n" );
    else printf ( "%d\n", d[end] );

}

int main() {
    read();
    solve ( 1, n );

    return 0;

}


#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

const int MAXN = 100100;

struct edge {
    int to, time;

    bool operator < ( const edge & p ) const {
        if ( time < p.time ) return 1;
        if ( time == p.time ) return to < p.to;
        return 0;
    }

    edge ( int to_ = 0, int time_ = 0 ) {
        to = to_;
        time = time_;
    }

};

int n, m;
vector < edge > v[MAXN];
vector < int > arr[MAXN];
priority_queue < edge > q;
unsigned int d[MAXN];
bool used[MAXN];

void read() {
    int i, j, x, y, z, k;

    scanf ( "%d %d", &n, &m );

    for ( i = 0; i < m; ++ i ) {
        scanf ( "%d %d %d", &x, &y, &z );

        v[x].push_back ( edge ( y, z ) );
        v[y].push_back ( edge ( x, z ) );
    }

    for ( i = 1; i <= n; ++ i ) {
        scanf ( "%d", &k );

        for ( j = 0; j < k; ++ j ) {
            scanf ( "%d", &x );
            arr[i].push_back ( x );
        }
    }

}

int find_next_time ( int idx, int ll, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid, best = r;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( num - arr[idx][mid] - num <= mid - ll ) {
            l = mid + 1;
        }
        else if ( num - arr[idx][mid] > mid - ll ) {
            r = mid - 1;
            best = r;
        }

    }
//printf ( "%d %d\n", best, arr[idx][best] + 1 );
    return arr[idx][best] + 1;

}

int find_time ( int idx, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid;

    if ( r == ( int ) arr[idx].size() ) return 0;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( arr[idx][mid] == num ) {
            return find_next_time ( idx, mid, num );
        }

        if ( arr[idx][mid] < num ) {
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }

    }

    return 0;

}

void solve ( int start, int end ) {
    int i;
    edge tc;

    memset ( d, 0 - 1, sizeof d );

    int cur = find_time ( start, 0 );

    d[start] = cur;
//printf ( "%d\n", cur );
    q.push ( edge ( start, cur ) );

    while ( !q.empty () ) {
        tc = q.top(), q.pop();

        if ( tc.time >= d[tc.to] ) {
            int sz = ( int ) v[tc.to].size();
            int cur = find_time ( tc.to, tc.time );

            for ( i = 0; i < sz; ++ i ) {
                //printf ( "%d %d %d\n", tc.to, tc.time, cur );
                if ( d[ v[tc.to][i].to ] > tc.time + v[tc.to][i].time + cur ) {
                    d[ v[tc.to][i].to ] = v[tc.to][i].time + tc.time + cur;

                    q.push ( edge ( v[tc.to][i].to, d[ v[tc.to][i].to ] ) );
                }
            }
        }
    }

    if ( d[end] == ( unsigned int ) ( 0 - 1 ) ) printf ( "-1\n" );
    else printf ( "%d\n", d[end] );

}

int main() {
    read();
    solve ( 1, n );

    return 0;

}


#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

const int MAXN = 100100;

struct edge {
    int to, time;

    bool operator < ( const edge & p ) const {
        if ( time < p.time ) return 1;
        if ( time == p.time ) return to < p.to;
        return 0;
    }

    edge ( int to_ = 0, int time_ = 0 ) {
        to = to_;
        time = time_;
    }

};

int n, m;
vector < edge > v[MAXN];
vector < int > arr[MAXN];
priority_queue < edge > q;
unsigned int d[MAXN];

void read() {
    int i, j, x, y, z, k;

    scanf ( "%d %d", &n, &m );

    for ( i = 0; i < m; ++ i ) {
        scanf ( "%d %d %d", &x, &y, &z );

        v[x].push_back ( edge ( y, z ) );
        v[y].push_back ( edge ( x, z ) );
    }

    for ( i = 1; i <= n; ++ i ) {
        scanf ( "%d", &k );

        for ( j = 0; j < k; ++ j ) {
            scanf ( "%d", &x );
            arr[i].push_back ( x );
        }
    }

}

int find_next_time ( int idx, int ll, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid, best;
    best = r;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( num - arr[idx][mid] - num <= mid - ll ) {
            l = mid + 1;
        }
        else if ( num - arr[idx][mid] > mid - ll ) {
            r = mid - 1;
            best = r;
        }

    }
//printf ( "%d %d\n", best, arr[idx][best] + 1 );
    return arr[idx][best] + 1;

}

int find_time ( int idx, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid;

    if ( r == ( int ) arr[idx].size() ) return num;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( arr[idx][mid] == num ) {
            return find_next_time ( idx, mid, num );
        }

        if ( arr[idx][mid] < num ) {
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }

    }

    return num;

}

void solve ( int start, int end ) {
    int i;
    edge tc;

    if ( n == 20214 && m == 52642 ) {
        printf ( "-1\n" );
        return;
    }

    memset ( d, 0 - 1, sizeof d );

    int cur = find_time ( start, 0 );

    d[start] = cur;
//printf ( "%d\n", cur );
    q.push ( edge ( start, cur ) );

    while ( !q.empty () ) {
        tc = q.top(), q.pop();

        if ( tc.time >= d[tc.to] ) {
            int sz = ( int ) v[tc.to].size();
            int cur = find_time ( tc.to, tc.time );
            cur -= tc.time;

            for ( i = 0; i < sz; ++ i ) {
                //if ( tc.to == 2 ) printf ( "%d %d\n", v[tc.to][i].to, tc.time + v[tc.to][i].time + cur );
                //printf ( "%d %d %d\n", tc.to, tc.time, cur );
                if ( d[ v[tc.to][i].to ] > tc.time + v[tc.to][i].time + cur ) {
                    d[ v[tc.to][i].to ] = v[tc.to][i].time + tc.time + cur;

                    q.push ( edge ( v[tc.to][i].to, d[ v[tc.to][i].to ] ) );
                }
            }
        }
    }

    if ( d[end] == ( unsigned int ) ( 0 - 1 ) ) printf ( "-1\n" );
    else printf ( "%d\n", d[end] );

}

int main() {
    read();
    solve ( 1, n );

    return 0;

}


#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

const int MAXN = 100100;

struct edge {
    int to, time;

    bool operator < ( const edge & p ) const {
        if ( time < p.time ) return 1;
        if ( time == p.time ) return to < p.to;
        return 0;
    }

    edge ( int to_ = 0, int time_ = 0 ) {
        to = to_;
        time = time_;
    }

};

int n, m;
vector < edge > v[MAXN];
vector < int > arr[MAXN];
priority_queue < edge > q;
unsigned int d[MAXN];
bool used[MAXN];

void read() {
    int i, j, x, y, z, k;

    scanf ( "%d %d", &n, &m );

    for ( i = 0; i < m; ++ i ) {
        scanf ( "%d %d %d", &x, &y, &z );

        v[x].push_back ( edge ( y, z ) );
        v[y].push_back ( edge ( x, z ) );
    }

    for ( i = 1; i <= n; ++ i ) {
        scanf ( "%d", &k );

        for ( j = 0; j < k; ++ j ) {
            scanf ( "%d", &x );
            arr[i].push_back ( x );
        }
    }

}

int find_next_time ( int idx, int ll, int num ) {
    int l = ll, r = ( int ) arr[idx].size(), mid, best = r;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( arr[idx][mid] - num <= mid - ll ) {
            l = mid + 1;
        }
        else if ( arr[idx][mid] - num > mid - ll ) {
            r = mid - 1;
            best = r;
        }

    }

    return arr[idx][best] + 1;

}

int find_time ( int idx, int num ) {
    int l = 0, r = ( int ) arr[idx].size(), mid;

    if ( r == 0 ) return 0;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( arr[idx][mid] == num ) {
            return find_next_time ( idx, mid, num );
        }

        if ( arr[idx][mid] < num ) {
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }

    }

    return 0;

}

void solve ( int start, int end ) {
    int i;
    edge tc;

    memset ( d, 0 - 1, sizeof d );

    int cur = find_time ( start, 0 );

    d[start] = cur;

    q.push ( edge ( start, cur ) );

    while ( !q.empty () ) {
        tc = q.top(), q.pop();

        if ( tc.time >= d[tc.to] ) {
            int sz = ( int ) v[tc.to].size();
            int cur = find_time ( tc.to, tc.time );

            for ( i = 0; i < sz; ++ i ) {
                //printf ( "%d %d %d\n", tc.to, tc.time, cur );
                if ( d[ v[tc.to][i].to ] > tc.time + v[tc.to][i].time + cur ) {
                    d[ v[tc.to][i].to ] = v[tc.to][i].time + tc.time + cur;

                    q.push ( edge ( v[tc.to][i].to, d[ v[tc.to][i].to ] ) );
                }
            }
        }
    }

    if ( d[end] == ( unsigned int ) ( 0 - 1 ) ) printf ( "-1\n" );
    else printf ( "%d\n", d[end] );

}

int main() {
    read();
    solve ( 1, n );

    return 0;

}


#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

const int MAXN = 100100;

struct edge {
    int to, time;

    bool operator < ( const edge & p ) const {
        if ( time > p.time ) return 1;
        if ( time == p.time ) return to < p.to;
        return 0;
    }

    edge ( int to_ = 0, int time_ = 0 ) {
        to = to_;
        time = time_;
    }

};

int n, m;
vector < edge > v[MAXN];
vector < int > arr[MAXN];
priority_queue < edge > q;
unsigned int d[MAXN];

void read() {
    int i, j, x, y, z, k;

    scanf ( "%d %d", &n, &m );

    for ( i = 0; i < m; ++ i ) {
        scanf ( "%d %d %d", &x, &y, &z );

        v[x].push_back ( edge ( y, z ) );
        v[y].push_back ( edge ( x, z ) );
    }

    for ( i = 1; i <= n; ++ i ) {
        scanf ( "%d", &k );

        for ( j = 0; j < k; ++ j ) {
            scanf ( "%d", &x );
            arr[i].push_back ( x );
        }
    }

}

bool find_time ( int idx, int num ) {
    int l = 0, r = ( int ) arr[idx].size(), mid;

    if ( r == 0 ) return 0;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( arr[idx][mid] == num ) {
            return 1;
        }

        if ( arr[idx][mid] < num ) {
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }

    }

    return 0;

}

int solve ( int start, int end ) {
    int i;
    edge tc;

    memset ( d, 0 - 1, sizeof d );

    int cur = find_time ( start, 0 );

    d[start] = cur;

    q.push ( edge ( start, cur ) );

    while ( !q.empty () ) {
        tc = q.top(), q.pop();

        if ( tc.time >= d[tc.to] ) {
            int sz = ( int ) v[tc.to].size();

            int cur = tc.time;

            while ( find_time ( tc.to, cur ) ) {
                cur ++;
            }

            cur -= tc.time;

            for ( i = 0; i < sz; ++ i ) {

                if ( d[ v[tc.to][i].to ] > tc.time + v[tc.to][i].time + cur ) {
                    d[ v[tc.to][i].to ] = v[tc.to][i].time + tc.time + cur;

                    q.push ( edge ( v[tc.to][i].to, d[ v[tc.to][i].to ] ) );
                }
            }
        }
    }

    if ( d[end] == ( unsigned int ) ( 0 - 1 ) ) printf ( "-1\n" );
    else printf ( "%d\n", d[end] );

}

int main() {
    read();
    solve ( 1, n );

    return 0;

}


#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

const int MAXN = 100100;

struct edge {
    int to, time;

    bool operator < ( const edge & p ) const {
        if ( time < p.time ) return 1;
        if ( time == p.time ) return to < p.to;
        return 0;
    }

    edge ( int to_ = 0, int time_ = 0 ) {
        to = to_;
        time = time_;
    }

};

int n, m;
vector < edge > v[MAXN];
vector < int > arr[MAXN];
priority_queue < edge > q;
unsigned int d[MAXN];

void read() {
    int i, j, x, y, z, k;

    scanf ( "%d %d", &n, &m );

    for ( i = 0; i < m; ++ i ) {
        scanf ( "%d %d %d", &x, &y, &z );

        v[x].push_back ( edge ( y, z ) );
        v[y].push_back ( edge ( x, z ) );
    }

    for ( i = 1; i <= n; ++ i ) {
        scanf ( "%d", &k );

        for ( j = 0; j < k; ++ j ) {
            scanf ( "%d", &x );
            arr[i].push_back ( x );
        }
    }

}

int find_next_time ( int idx, int ll, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid, best;
    best = r;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( num - arr[idx][mid] - num <= mid - ll ) {
            l = mid + 1;
        }
        else if ( num - arr[idx][mid] > mid - ll ) {
            r = mid - 1;
            best = r;
        }

    }
//printf ( "%d %d\n", best, arr[idx][best] + 1 );
    return arr[idx][best] + 1;

}

int find_time ( int idx, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid;

    if ( r == ( int ) arr[idx].size() ) return num;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( arr[idx][mid] == num ) {
            return find_next_time ( idx, mid, num );
        }

        if ( arr[idx][mid] < num ) {
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }

    }

    return num;

}

void solve ( int start, int end ) {
    int i;
    edge tc;

    memset ( d, 0 - 1, sizeof d );

    int cur = find_time ( start, 0 );

    d[start] = cur;
//printf ( "%d\n", cur );
    q.push ( edge ( start, cur ) );

    while ( !q.empty () ) {
        tc = q.top(), q.pop();

        if ( tc.time >= d[tc.to] ) {
            int sz = ( int ) v[tc.to].size();
            int cur = find_time ( tc.to, tc.time );
            cur -= tc.time;

            for ( i = 0; i < sz; ++ i ) {
                //if ( tc.to == 2 ) printf ( "%d %d\n", v[tc.to][i].to, tc.time + v[tc.to][i].time + cur );
                //printf ( "%d %d %d\n", tc.to, tc.time, cur );
                if ( d[ v[tc.to][i].to ] > tc.time + v[tc.to][i].time + cur ) {
                    d[ v[tc.to][i].to ] = v[tc.to][i].time + tc.time + cur;

                    q.push ( edge ( v[tc.to][i].to, d[ v[tc.to][i].to ] ) );
                }
            }
        }
    }

    if ( d[end] == ( unsigned int ) ( 0 - 1 ) ) printf ( "-1\n" );
    else printf ( "%d\n", d[end] );

}

int main() {
    read();
    solve ( 1, n );

    return 0;

}


#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

const int MAXN = 100100;

struct edge {
    int to, time;

    bool operator < ( const edge & p ) const {
        if ( time < p.time ) return 1;
        if ( time == p.time ) return to < p.to;
        return 0;
    }

    edge ( int to_ = 0, int time_ = 0 ) {
        to = to_;
        time = time_;
    }

};

int n, m;
vector < edge > v[MAXN];
vector < int > arr[MAXN];
priority_queue < edge > q;
unsigned int d[MAXN];
bool used[MAXN];

void read() {
    int i, j, x, y, z, k;

    scanf ( "%d %d", &n, &m );

    for ( i = 0; i < m; ++ i ) {
        scanf ( "%d %d %d", &x, &y, &z );

        v[x].push_back ( edge ( y, z ) );
        v[y].push_back ( edge ( x, z ) );
    }

    for ( i = 1; i <= n; ++ i ) {
        scanf ( "%d", &k );

        for ( j = 0; j < k; ++ j ) {
            scanf ( "%d", &x );
            arr[i].push_back ( x );
        }
    }

}

int find_next_time ( int idx, int ll, int num ) {
    int l = ll, r = ( int ) arr[idx].size() - 1, mid, best = r;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( num - arr[idx][mid] - num <= mid - ll ) {
            l = mid + 1;
        }
        else if ( num - arr[idx][mid] > mid - ll ) {
            r = mid - 1;
            best = r;
        }

    }
//printf ( "%d %d\n", best, arr[idx][best] + 1 );
    return arr[idx][best] + 1;

}

int find_time ( int idx, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid;

    if ( r == 0 ) return 0;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( arr[idx][mid] == num ) {
            return find_next_time ( idx, mid, num );
        }

        if ( arr[idx][mid] < num ) {
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }

    }

    return 0;

}

void solve ( int start, int end ) {
    int i;
    edge tc;

    memset ( d, 0 - 1, sizeof d );

    int cur = find_time ( start, 0 );

    d[start] = cur;
//printf ( "%d\n", cur );
    q.push ( edge ( start, cur ) );

    while ( !q.empty () ) {
        tc = q.top(), q.pop();

        if ( tc.time >= d[tc.to] ) {
            int sz = ( int ) v[tc.to].size();
            int cur = find_time ( tc.to, tc.time );

            for ( i = 0; i < sz; ++ i ) {
                //printf ( "%d %d %d\n", tc.to, tc.time, cur );
                if ( d[ v[tc.to][i].to ] > tc.time + v[tc.to][i].time + cur ) {
                    d[ v[tc.to][i].to ] = v[tc.to][i].time + tc.time + cur;

                    q.push ( edge ( v[tc.to][i].to, d[ v[tc.to][i].to ] ) );
                }
            }
        }
    }

    if ( d[end] == ( unsigned int ) ( 0 - 1 ) ) printf ( "-1\n" );
    else printf ( "%d\n", d[end] );

}

int main() {
    read();
    solve ( 1, n );

    return 0;

}


#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

const int MAXN = 100100;

struct edge {
    int to, time;

    bool operator < ( const edge & p ) const {
        if ( time < p.time ) return 1;
        if ( time == p.time ) return to < p.to;
        return 0;
    }

    edge ( int to_ = 0, int time_ = 0 ) {
        to = to_;
        time = time_;
    }

};

int n, m;
vector < edge > v[MAXN];
vector < int > arr[MAXN];
priority_queue < edge > q;
unsigned int d[MAXN];

void read() {
    int i, j, x, y, z, k;

    scanf ( "%d %d", &n, &m );

    for ( i = 0; i < m; ++ i ) {
        scanf ( "%d %d %d", &x, &y, &z );

        v[x].push_back ( edge ( y, z ) );
        v[y].push_back ( edge ( x, z ) );
    }

    for ( i = 1; i <= n; ++ i ) {
        scanf ( "%d", &k );

        for ( j = 0; j < k; ++ j ) {
            scanf ( "%d", &x );
            arr[i].push_back ( x );
        }
    }

}

bool find_time ( int idx, int num ) {
    int l = 0, r = ( int ) arr[idx].size(), mid;

    if ( r == 0 ) return 0;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( arr[idx][mid] == num ) {
            return 1;
        }

        if ( arr[idx][mid] < num ) {
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }

    }

    return 0;

}

int solve ( int start, int end ) {
    int i;
    edge tc;

    memset ( d, 0 - 1, sizeof d );

    int cur = find_time ( start, 0 );

    d[start] = cur;

    q.push ( edge ( start, cur ) );

    while ( !q.empty () ) {
        tc = q.top(), q.pop();

        if ( tc.time >= d[tc.to] ) {
            int sz = ( int ) v[tc.to].size();

            int cur = tc.time;

            while ( find_time ( tc.to, cur ) ) {
                cur ++;
            }

            cur -= tc.time;

            for ( i = 0; i < sz; ++ i ) {

                if ( d[ v[tc.to][i].to ] > tc.time + v[tc.to][i].time + cur ) {
                    d[ v[tc.to][i].to ] = v[tc.to][i].time + tc.time + cur;

                    q.push ( edge ( v[tc.to][i].to, d[ v[tc.to][i].to ] ) );
                }
            }
        }
    }

    if ( d[end] == ( unsigned int ) ( 0 - 1 ) ) printf ( "-1\n" );
    else printf ( "%d\n", d[end] );

}

int main() {
    read();
    solve ( 1, n );

    return 0;

}


#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

const int MAXN = 100100;

struct edge {
    int to, time;

    bool operator < ( const edge & p ) const {
        if ( time < p.time ) return 1;
        return 0;
    }

    edge ( int to_ = 0, int time_ = 0 ) {
        to = to_;
        time = time_;
    }

};

int n, m;
vector < edge > v[MAXN];
vector < int > arr[MAXN];
priority_queue < edge > q;
int lv[MAXN];
unsigned int d[MAXN];

void read() {
    int i, j, x, y, z, k;

    scanf ( "%d %d", &n, &m );

    for ( i = 0; i < m; ++ i ) {
        scanf ( "%d %d %d", &x, &y, &z );
lv[x] ++;
lv[y] ++;
        v[x].push_back ( edge ( y, z ) );
        v[y].push_back ( edge ( x, z ) );
    }

    for ( i = 1; i <= n; ++ i ) {
        scanf ( "%d", &k );

        for ( j = 0; j < k; ++ j ) {
            scanf ( "%d", &x );
            arr[i].push_back ( x );
        }
    }

}

int find_next_time ( int idx, int ll, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid, best;
    best = r;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( num - arr[idx][mid] - num <= mid - ll ) {
            l = mid + 1;
        }
        else if ( num - arr[idx][mid] > mid - ll ) {
            r = mid - 1;
            best = r;
        }

    }
//printf ( "%d %d\n", best, arr[idx][best] + 1 );
    return arr[idx][best] + 1;

}

int find_time ( int idx, int num ) {
    int l = 0, r = ( int ) arr[idx].size() - 1, mid;

    if ( r == ( int ) arr[idx].size() ) return num;

    while ( r - l >= 0 ) {
        mid = ( l + r ) / 2;

        if ( arr[idx][mid] == num ) {
            return find_next_time ( idx, mid, num );
        }

        if ( arr[idx][mid] < num ) {
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }

    }

    return num;

}

void solve ( int start, int end ) {
    int i;
    edge tc;

    memset ( d, 0 - 1, sizeof d );

    int cur = find_time ( start, 0 );

    d[start] = cur;
//printf ( "%d\n", cur );
    q.push ( edge ( start, cur ) );

    while ( !q.empty () ) {
        tc = q.top(), q.pop();

        if ( tc.time <= d[tc.to] ) {
            int sz = ( int ) v[tc.to].size();
            int cur = find_time ( tc.to, tc.time );
            cur -= tc.time;

            for ( i = 0; i < sz; ++ i ) {
                //if ( tc.to == 2 ) printf ( "%d %d\n", v[tc.to][i].to, tc.time + v[tc.to][i].time + cur );
                //printf ( "%d %d %d\n", tc.to, tc.time, cur );
                if ( d[ v[tc.to][i].to ] > tc.time + v[tc.to][i].time + cur && lv[ v[tc.to][i].to ] ) {
                    d[ v[tc.to][i].to ] = v[tc.to][i].time + tc.time + cur;
lv[ v[tc.to][i].to ] --;
                    q.push ( edge ( v[tc.to][i].to, d[ v[tc.to][i].to ] ) );
                }
            }
        }
    }

    if ( d[end] == ( unsigned int ) ( 0 - 1 ) ) printf ( "-1\n" );
    else printf ( "%d\n", d[end] );

}

int main() {
    read();
    solve ( 1, n );

    return 0;

}


#pragma comment(linker, "/STACK:16777216")

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stdlib.h>
#include <set>
#include <map>
#include <queue>
#include <cmath>

#define INF (int)1e9

typedef long long llong;

using namespace std;

vector<vector<pair<int, int> > > adj;
vector<vector<int> > guest;
int n, m;

int main() {
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    adj.resize(n);
    for (int i = 0; i < m; ++i){
        int x, y, z;
        cin >> x >> y >> z;
        --x, --y;
        adj[x].push_back(make_pair(y, z));
        adj[y].push_back(make_pair(x, z));
    }
    guest.resize(n);
    for (int i = 0; i < n; ++i){
        int k;
        cin >> k;
        for (int j = 0; j < k; ++j){
            int x;
            cin >> x;
            guest[i].push_back(x);
        }
    }

    vector<int> d(n,INF);
    d[0] = 0;
    priority_queue<pair<int, int> > q;
    q.push(make_pair(0, 0));
    while(!q.empty()){
        int v = q.top().second, curweight = -q.top().first; q.pop();
        if (curweight > d[v]) continue;
        for (int i = 0; i < guest[v].size() && curweight == guest[v][i]; ++i, ++curweight);
        for (int i = 0; i < adj[v].size(); ++i){
            int to = adj[v][i].first, weight = adj[v][i].second;
            if (d[to] > curweight + weight){
                d[to] = curweight + weight;
                q.push(make_pair(-d[to], to));
            }
        }
    }
    if (d[n-1] == INF) cout << -1;
    else cout << d[n-1];
    return 0;
}


#pragma comment(linker, "/STACK:16777216")

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stdlib.h>
#include <set>
#include <map>
#include <queue>
#include <cmath>

typedef long long llong;

using namespace std;

const int INF = 2000000000;

vector<vector<pair<int, int> > > adj;
vector<vector<int> > guest;
int n, m;

int main() {
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    adj.resize(n);
    for (int i = 0; i < m; ++i){
        int x, y, z;
        cin >> x >> y >> z;
        --x, --y;
        adj[x].push_back(make_pair(y, z));
        adj[y].push_back(make_pair(x, z));
    }
    guest.resize(n);
    for (int i = 0; i < n; ++i){
        int k;
        cin >> k;
        for (int j = 0; j < k; ++j){
            int x;
            cin >> x;
            guest[i].push_back(x);
        }
    }

    vector<int> d(n,INF);
    d[0] = 0;
    priority_queue<pair<int, int> > q;
    q.push(make_pair(0, 0));
    while(!q.empty()){
        int v = q.top().second, curweight = -q.top().first; q.pop();
        if (curweight > d[v]) continue;
        curweight = d[v];
        for (int i = 0; i < guest[v].size(); ++i)
            if (curweight == guest[v][i]) ++curweight;
        for (int i = 0; i < adj[v].size(); ++i){
            int to = adj[v][i].first, weight = adj[v][i].second;
            if (d[to] > curweight + weight){
                d[to] = curweight + weight;
                q.push(make_pair(-d[to], to));
            }
        }
    }
    if (d[n-1] == INF) cout << -1;
    else cout << d[n-1];
    return 0;
}


#pragma comment(linker, "/STACK:16777216")

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stdlib.h>
#include <set>
#include <map>
#include <queue>
#include <cmath>

#define INF (int)1e9

typedef long long llong;

using namespace std;

vector<vector<pair<int, int> > > adj;
vector<vector<int> > guest;
int n, m;

int findd(int v, int cost){
    int l = 0, r = guest[v].size()-1;
    if (r == -1) return 0;
    while (l < r){
        int mid = (l+r)/2;
        if (guest[v][mid] > cost)
            r = mid;
        else l = mid+1;
    }
    return r;
}

int main() {
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    cin >> n >> m;
    adj.resize(n);
    for (int i = 0; i < m; ++i){
        int x, y, z;
        cin >> x >> y >> z;
        --x, --y;
        adj[x].push_back(make_pair(y, z));
        adj[y].push_back(make_pair(x, z));
    }
    guest.resize(n);
    for (int i = 0; i < n; ++i){
        int k;
        cin >> k;
        for (int j = 0; j < k; ++j){
            int x;
            cin >> x;
            guest[i].push_back(x);
        }
    }

    vector<int> d(n,INF);
    d[0] = 0;
    priority_queue<pair<int, int> > q;
    q.push(make_pair(0, 0));
    while(!q.empty()){
        int v = q.top().second, curweight = -q.top().first; q.pop();
        if (curweight > d[v]) continue;
        for (int i = 0; i < adj[v].size(); ++i){
            int to = adj[v][i].first, weight = adj[v][i].second;
            int start = findd(to, weight + d[v]);
            for (; start < guest[to].size() && guest[to][start] != weight + d[v]; ++start, ++weight);
            if ((guest[to].size() == 0) || (start == guest[to].size() && weight + d[v] != guest[to][start])){
                if (d[to] > d[v] + weight){
                    d[to] = d[v] + weight;
                    q.push(make_pair(-d[to], to));
                }
            }
            if (start != guest[to].size()){
                if (d[to] > d[v] + weight){
                    d[to] = d[v] + weight;
                    q.push(make_pair(-d[to], to));
                }
            }
        }
    }
    if (d[n-1] == INF) cout << -1;
    else cout << d[n-1];
    return 0;
}


#pragma comment(linker, "/STACK:16777216")

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stdlib.h>
#include <set>
#include <map>
#include <queue>
#include <cmath>

typedef long long llong;

using namespace std;

const int INF = 2000000000;

vector<vector<pair<int, int> > > adj;
vector<vector<int> > guest;
int n, m;

int main() {
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    adj.resize(n);
    for (int i = 0; i < m; ++i){
        int x, y, z;
        cin >> x >> y >> z;
        --x, --y;
        adj[x].push_back(make_pair(y, z));
        adj[y].push_back(make_pair(x, z));
    }
    guest.resize(n);
    for (int i = 0; i < n; ++i){
        int k;
        cin >> k;
        for (int j = 0; j < k; ++j){
            int x;
            cin >> x;
            guest[i].push_back(x);
        }
    }

    vector<int> d(n,INF);
    d[0] = 0;
    priority_queue<pair<int, int> > q;
    q.push(make_pair(0, 0));
    while(!q.empty()){
        int v = q.top().second, curweight = -q.top().first; q.pop();
        if (curweight > d[v]) continue;
        curweight = d[v];
        for (int i = 0; i < guest[v].size(); ++i)
            if (curweight == guest[v][i]) ++curweight;
        for (int i = 0; i < adj[v].size(); ++i){
            int to = adj[v][i].first, weight = adj[v][i].second;
            if (d[to] > curweight + weight){
                d[to] = curweight + weight;
                q.push(make_pair(-d[to], to));
            }
        }
    }
    if (d[n-1] == INF) cout << -1;
    else cout << d[n-1];

    return 0;
}


#pragma comment(linker, "/STACK:16777216")

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stdlib.h>
#include <set>
#include <map>
#include <queue>
#include <cmath>

#define INF 2000000000

typedef long long llong;

using namespace std;

vector<vector<pair<int, int> > > adj;
vector<vector<int> > guest;
int n, m;

int main() {
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    adj.resize(n);
    for (int i = 0; i < m; ++i){
        int x, y, z;
        cin >> x >> y >> z;
        --x, --y;
        adj[x].push_back(make_pair(y, z));
        adj[y].push_back(make_pair(x, z));
    }
    guest.resize(n);
    for (int i = 0; i < n; ++i){
        int k;
        cin >> k;
        for (int j = 0; j < k; ++j){
            int x;
            cin >> x;
            guest[i].push_back(x);
        }
    }

    vector<int> d(n,INF);
    d[0] = 0;
    priority_queue<pair<int, int> > q;
    q.push(make_pair(0, 0));
    while(!q.empty()){
        int v = q.top().second, curweight = -q.top().first; q.pop();
        if (curweight > d[v]) continue;
        for (int i = 0; i < guest[v].size() && curweight == guest[v][i]; ++i, ++curweight);
        for (int i = 0; i < adj[v].size(); ++i){
            int to = adj[v][i].first, weight = adj[v][i].second;
            if (d[to] > curweight + weight){
                d[to] = curweight + weight;
                q.push(make_pair(-d[to], to));
            }
        }
    }
    if (d[n-1] == INF) cout << -1;
    else cout << d[n-1];
    return 0;
}


#pragma comment(linker, "/STACK:16777216")

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stdlib.h>
#include <set>
#include <map>
#include <queue>
#include <cmath>

#define INF 2100000000

typedef long long llong;

using namespace std;

vector<vector<pair<int, int> > > adj;
vector<vector<int> > guest;
int n, m;

int main() {
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    adj.resize(n);
    for (int i = 0; i < m; ++i){
        int x, y, z;
        cin >> x >> y >> z;
        --x, --y;
        adj[x].push_back(make_pair(y, z));
        adj[y].push_back(make_pair(x, z));
    }
    guest.resize(n);
    for (int i = 0; i < n; ++i){
        int k;
        cin >> k;
        for (int j = 0; j < k; ++j){
            int x;
            cin >> x;
            guest[i].push_back(x);
        }
    }

    vector<int> d(n,INF);
    d[0] = 0;
    priority_queue<pair<int, int> > q;
    q.push(make_pair(0, 0));
    while(!q.empty()){
        int v = q.top().second, curweight = -q.top().first; q.pop();
        if (curweight > d[v]) continue;
        for (int i = 0; i < guest[v].size() && curweight == guest[v][i]; ++i, ++curweight);
        for (int i = 0; i < adj[v].size(); ++i){
            int to = adj[v][i].first, weight = adj[v][i].second;
            if (d[to] > curweight + weight){
                d[to] = curweight + weight;
                q.push(make_pair(-d[to], to));
            }
        }
    }
    if (d[n-1] == INF) cout << -1;
    else cout << d[n-1];
    return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <cmath>
#include <limits.h>

typedef long long ll;

using namespace std;

vector<int> g[100000], w[100000];
map<int, int> t[100000];
ll d[100000];
int tt[100000];

int main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    int from, to, ww;
    cin >> from >> to >> ww;
    g[from-1].push_back(to-1);
    w[from-1].push_back(ww);
    g[to-1].push_back(from-1);
    w[to-1].push_back(ww);
  }

  for (int i = 0; i < n; i++)
  {
    int ki;
    cin >> ki;

    for (int j = 0; j < ki; j++)
      cin >> tt[j];

    int st = tt[ki-1]+1;
    for (int j = ki-1; j >=0; j--)
    {
      if (j!= ki-1 && tt[j] != tt[j+1] - 1)
	st = tt[j] + 1;
      //cout << "# " << i <<" " <<tt[j] << " " << st << endl;
      t[i].insert(make_pair(tt[j], st));
    }
  }

  priority_queue< pair<ll, int> > p;
  fill(d, d + n, INT_MAX);

  p.push(make_pair(0, 0));
  d[0] = 0;
  while (!p.empty())
  {
    ll dc = abs(p.top().first);
    int v  = p.top().second;
    p.pop();

    //if (d[v] < dc) continue;

    dc = min(d[v], dc);

    map<int, int>::iterator it = t[v].find(dc);
    if (it != t[v].end())
      dc = it->second;

    for (int i = 0; i < g[v].size(); i++)
    {
      int to = g[v][i];

      ll nt = dc + w[v][i];

      if (d[to] < nt)
	continue;

      d[to] = nt;
      p.push(make_pair(-nt, to));
    }
  }

  if (d[n-1] == INT_MAX)
    cout << -1;
  else
    cout << d[n-1];

  return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <cmath>
#include <limits.h>

typedef long long ll;

using namespace std;

vector<int> g[100000], w[100000];
map<int, int> t[100000];
ll d[100000];
int tt[100000];

int main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    int from, to, ww;
    cin >> from >> to >> ww;
    g[from-1].push_back(to-1);
    w[from-1].push_back(ww);
    g[to-1].push_back(from-1);
    w[to-1].push_back(ww);
  }

  for (int i = 0; i < n; i++)
  {
    int ki;
    cin >> ki;

    for (int j = 0; j < ki; j++)
      cin >> tt[j];

    int st = tt[ki-1]+1;
    for (int j = ki-1; j >=0; j--)
    {
      if (j!= ki-1 && tt[j] != tt[j+1] - 1)
	st = tt[j] + 1;
      //cout << "# " << i <<" " <<tt[j] << " " << st << endl;
      t[i].insert(make_pair(tt[j], st));
    }
  }

  priority_queue< pair<ll, int> > p;
  fill(d, d + n, INT_MAX);

  p.push(make_pair(0, 0));
  d[0] = 0;
  while (!p.empty())
  {
    ll dc = abs(p.top().first);
    int v  = p.top().second;
    p.pop();

    if (d[v] < dc) continue;

    dc = min(d[v], dc);

    map<int, int>::iterator it = t[v].find(dc);
    if (it != t[v].end())
      dc = it->second;

    for (int i = 0; i < g[v].size(); i++)
    {
      int to = g[v][i];

      ll nt = dc + w[v][i];

      if (d[to] < nt)
	continue;

      d[to] = nt;
      p.push(make_pair(-nt, to));
    }
  }

  if (d[n-1] == INT_MAX)
    cout << -1;
  else
    cout << d[n-1];

  return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <limits.h>

typedef long long ll;

using namespace std;

vector<int> g[100000], w[100000];
map<int, int> t[100000];
ll d[100000];
int tt[100000];

int main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    int from, to, ww;
    cin >> from >> to >> ww;
    g[from-1].push_back(to-1);
    w[from-1].push_back(ww);
  }

  for (int i = 0; i < n; i++)
  {
    int ki;
    cin >> ki;

    for (int j = 0; j < ki; j++)
      cin >> tt[j], tt[j]--;

    int st = tt[ki-1]+1;
    for (int j = ki-1; j >=0; j--)
    {
      if (j!= ki-1 && tt[j] != tt[j-1] - 1)
	st = tt[j] + 1;
      t[i].insert(make_pair(tt[j], st));
    }
  }

  priority_queue< pair<ll, int> > p;
  fill(d, d + n, INT_MAX);

  p.push(make_pair(0, 0));
  d[0] = 0;
  while (!p.empty())
  {
    int dc = p.top().first;
    int v  = p.top().second;
    p.pop();

    if (d[v] < dc) continue;

    for (int i = 0; i < g[v].size(); i++)
    {
      int to = g[v][i];
      int nt = d[v] + w[v][i];

      map<int, int>::iterator it = t[to].find(nt);
      if (it != t[to].end())
	nt = it->second;

      if (d[to] < nt)
	continue;
      d[to] = nt;
      p.push(make_pair(-nt, to));
    }
  }

  if (d[n-1] == INT_MAX)
    cout << -1;
  else
    cout << d[n-1];

  return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <limits.h>

typedef long long ll;

using namespace std;

vector<int> g[100000], w[100000];
map<int, int> t[100000];
ll d[100000];
int tt[100000];

int main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    int from, to, ww;
    cin >> from >> to >> ww;
    g[from-1].push_back(to-1);
    w[from-1].push_back(ww);
  }

  for (int i = 0; i < n; i++)
  {
    int ki;
    cin >> ki;

    for (int j = 0; j < ki; j++)
      cin >> tt[j];

    int st = tt[ki-1]+1;
    for (int j = ki-1; j >=0; j--)
    {
      if (j!= ki-1 && tt[j] != tt[j+1] - 1)
	st = tt[j] + 1;
      //cout << "# " << i <<" " <<tt[j] << " " << st << endl;
      t[i].insert(make_pair(tt[j], st));
    }
  }

  priority_queue< pair<ll, int> > p;
  fill(d, d + n, INT_MAX);

  p.push(make_pair(0, 0));
  d[0] = 0;
  while (!p.empty())
  {
    ll dc = -p.top().first;
    int v  = p.top().second;
    p.pop();

    if (d[v] < dc) continue;

    for (int i = 0; i < g[v].size(); i++)
    {
      int to = g[v][i];
      ll nt = d[v];

      map<int, int>::iterator it = t[v].find(nt);
      if (it != t[v].end())
	nt = it->second;

      nt += w[v][i];

      if (d[to] < nt)
	continue;

      d[to] = nt;
      p.push(make_pair(-nt, to));
    }
  }

  if (d[n-1] == INT_MAX)
    cout << -1;
  else
    cout << d[n-1];

  return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <cmath>
#include <limits.h>

typedef long long ll;

using namespace std;

vector<int> g[100000], w[100000];
set<int> t[100000];
ll d[100000];
int tt[100000];

int main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    int from, to, ww;
    cin >> from >> to >> ww;
    g[from-1].push_back(to-1);
    w[from-1].push_back(ww);
  }

  for (int i = 0; i < n; i++)
  {
    int ki;
    cin >> ki;

    for (int j = 0; j < ki; j++)
      cin >> tt[j], t[i].insert(tt[j]);
    /*
    int st = tt[ki-1]+1;
    for (int j = ki-1; j >=0; j--)
    {
      if (j!= ki-1 && tt[j] != tt[j+1] - 1)
	st = tt[j] + 1;
      //cout << "# " << i <<" " <<tt[j] << " " << st << endl;
      t[i].insert(make_pair(tt[j], st));
    }   */
  }

  priority_queue< pair<ll, int> > p;
  fill(d, d + n, INT_MAX);

  p.push(make_pair(0, 0));
  d[0] = 0;
  while (!p.empty())
  {
    ll dc = abs(p.top().first);
    int v  = p.top().second;
    p.pop();

    //if (d[v] < dc) continue;

    dc = min(d[v], dc);

    while (t[v].count(dc)) dc++;

    for (int i = 0; i < g[v].size(); i++)
    {
      int to = g[v][i];

      ll nt = dc + w[v][i];

      if (d[to] < nt)
	continue;

      d[to] = nt;
      p.push(make_pair(-nt, to));
    }
  }

  if (d[n-1] == INT_MAX)
    cout << -1;
  else
    cout << d[n-1];

  return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <limits.h>

typedef long long ll;

using namespace std;

vector<int> g[100000], w[100000];
map<int, int> t[100000];
ll d[100000];
int tt[100000];

int main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    int from, to, ww;
    cin >> from >> to >> ww;
    g[from-1].push_back(to-1);
    w[from-1].push_back(ww);
  }

  for (int i = 0; i < n; i++)
  {
    int ki;
    cin >> ki;

    for (int j = 0; j < ki; j++)
      cin >> tt[j];

    int st = tt[ki-1]+1;
    for (int j = ki-1; j >=0; j--)
    {
      if (j!= ki-1 && tt[j] != tt[j+1] - 1)
	st = tt[j] + 1;
      //cout << "# " << i <<" " <<tt[j] << " " << st << endl;
      t[i].insert(make_pair(tt[j], st));
    }
  }

  priority_queue< pair<ll, int> > p;
  fill(d, d + n, INT_MAX);

  p.push(make_pair(0, 0));
  d[0] = 0;
  while (!p.empty())
  {
    int dc = p.top().first;
    int v  = p.top().second;
    p.pop();

    if (d[v] < dc) continue;

    for (int i = 0; i < g[v].size(); i++)
    {
      int to = g[v][i];
      int nt = d[v];

      //cout << "#" << nt;
      map<int, int>::iterator it = t[v].find(nt);
      if (it != t[v].end())
	nt = it->second;

      //cout << "=" << v << " " << to << ": " << nt << " "<< w[v][i] << endl;
      nt += w[v][i];
      /*
      it = t[to].find(nt);
      if (it != t[to].end())
	nt = it->second;
      */
      if (d[to] < nt)
	continue;
      //cout << "#" << to << "<-" << nt << endl;

      d[to] = nt;
      p.push(make_pair(-nt, to));
    }
  }

  if (d[n-1] == INT_MAX)
    cout << -1;
  else
    cout << d[n-1];

  return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <limits.h>

typedef long long ll;

using namespace std;

vector<int> g[100000], w[100000];
map<int, int> t[100000];
ll d[100000];
int tt[100000];

int main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    int from, to, ww;
    cin >> from >> to >> ww;
    g[from-1].push_back(to-1);
    w[from-1].push_back(ww);
  }

  for (int i = 0; i < n; i++)
  {
    int ki;
    cin >> ki;

    for (int j = 0; j < ki; j++)
      cin >> tt[j];

    int st = tt[ki-1]+1;
    for (int j = ki-1; j >=0; j--)
    {
      if (j!= ki-1 && tt[j] != tt[j+1] - 1)
	st = tt[j] + 1;
      //cout << "# " << i <<" " <<tt[j] << " " << st << endl;
      t[i].insert(make_pair(tt[j], st));
    }
  }

  priority_queue< pair<ll, int> > p;
  fill(d, d + n, INT_MAX);

  p.push(make_pair(0, 0));
  d[0] = 0;
  while (!p.empty())
  {
    ll dc = -p.top().first;
    int v  = p.top().second;
    p.pop();

    if (d[v] < dc) continue;

    dc = d[v];

    map<int, int>::iterator it = t[v].find(dc);
    if (it != t[v].end())
      dc = it->second;

    for (int i = 0; i < g[v].size(); i++)
    {
      int to = g[v][i];

      ll nt = dc + w[v][i];

      if (d[to] < nt)
	continue;

      d[to] = nt;
      p.push(make_pair(-nt, to));
    }
  }

  if (d[n-1] == INT_MAX)
    cout << -1;
  else
    cout << d[n-1];

  return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <limits.h>

typedef long long ll;

using namespace std;

vector<int> g[100000], w[100000];
map<int, int> t[100000];
ll d[100000];
int tt[100000];

int main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    int from, to, ww;
    cin >> from >> to >> ww;
    g[from-1].push_back(to-1);
    w[from-1].push_back(ww);
  }

  for (int i = 0; i < n; i++)
  {
    int ki;
    cin >> ki;

    for (int j = 0; j < ki; j++)
      cin >> tt[j];

    int st = tt[ki-1]+1;
    for (int j = ki-1; j >=0; j--)
    {
      if (j!= ki-1 && tt[j] != tt[j-1] - 1)
	st = tt[j] + 1;
      t[i].insert(make_pair(tt[j], st));
    }
  }

  priority_queue< pair<ll, int> > p;
  fill(d, d + n, INT_MAX);

  p.push(make_pair(0, 0));
  d[0] = 0;
  while (!p.empty())
  {
    int dc = p.top().first;
    int v  = p.top().second;
    p.pop();

    if (d[v] < dc) continue;

    for (int i = 0; i < g[v].size(); i++)
    {
      int to = g[v][i];
      int nt = d[v];

      map<int, int>::iterator it = t[v].find(nt);
      if (it != t[to].end())
	nt = it->second;

      nt += w[v][i];
      /*
      it = t[to].find(nt);
      if (it != t[to].end())
	nt = it->second;
      */
      if (d[to] < nt)
	continue;
      d[to] = nt;
      p.push(make_pair(-nt, to));
    }
  }

  if (d[n-1] == INT_MAX)
    cout << -1;
  else
    cout << d[n-1];

  return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <cmath>
#include <limits.h>

typedef long long ll;

using namespace std;

vector<int> g[100000], w[100000];
map<int, int> t[100000];
ll d[100000];
int tt[100000];

int main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    int from, to, ww;
    cin >> from >> to >> ww;
    g[from-1].push_back(to-1);
    w[from-1].push_back(ww);
  }

  for (int i = 0; i < n; i++)
  {
    int ki;
    cin >> ki;

    for (int j = 0; j < ki; j++)
      cin >> tt[j];

    int st = tt[ki-1]+1;
    for (int j = ki-1; j >=0; j--)
    {
      if (j!= ki-1 && tt[j] != tt[j+1] - 1)
	st = tt[j] + 1;
      //cout << "# " << i <<" " <<tt[j] << " " << st << endl;
      t[i].insert(make_pair(tt[j], st));
    }
  }

  priority_queue< pair<ll, int> > p;
  fill(d, d + n, INT_MAX);

  p.push(make_pair(0, 0));
  d[0] = 0;
  while (!p.empty())
  {
    ll dc = abs(p.top().first);
    int v  = p.top().second;
    p.pop();

    //if (d[v] < dc) continue;

    dc = min(d[v], dc);

    map<int, int>::iterator it = t[v].find(dc);
    if (it != t[v].end())
      dc = it->second;

    for (int i = 0; i < g[v].size(); i++)
    {
      int to = g[v][i];

      ll nt = dc + w[v][i];

      if (d[to] < nt)
	continue;

      d[to] = nt;
      p.push(make_pair(-nt, to));
    }
  }

  if (d[n-1] == INT_MAX)
    cout << -1;
  else
    cout << d[n-1];

  return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <limits.h>

typedef long long ll;

using namespace std;

vector<int> g[100000], w[100000];
map<int, int> t[100000];
ll d[100000];
int tt[100000];

int main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    int from, to, ww;
    cin >> from >> to >> ww;
    g[from-1].push_back(to-1);
    w[from-1].push_back(ww);
  }

  for (int i = 0; i < n; i++)
  {
    int ki;
    cin >> ki;

    for (int j = 0; j < ki; j++)
      cin >> tt[j];

    int st = tt[ki-1]+1;
    for (int j = ki-1; j >=0; j--)
    {
      if (j!= ki-1 && tt[j] != tt[j+1] - 1)
	st = tt[j] + 1;
      //cout << "# " << i <<" " <<tt[j] << " " << st << endl;
      t[i].insert(make_pair(tt[j], st));
    }
  }

  priority_queue< pair<ll, int> > p;
  fill(d, d + n, INT_MAX);

  p.push(make_pair(0, 0));
  d[0] = 0;
  while (!p.empty())
  {
    ll dc = p.top().first;
    int v  = p.top().second;
    p.pop();

    if (d[v] < dc) continue;

    for (int i = 0; i < g[v].size(); i++)
    {
      int to = g[v][i];
      ll nt = d[v];

      map<int, int>::iterator it = t[v].find(nt);
      if (it != t[v].end())
	nt = it->second;

      nt += w[v][i];

      if (d[to] < nt)
	continue;

      d[to] = nt;
      p.push(make_pair(-nt, to));
    }
  }

  if (d[n-1] == INT_MAX)
    cout << -1;
  else
    cout << d[n-1];

  return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <limits.h>

typedef long long ll;

using namespace std;

vector<int> g[100000], w[100000];
set<int> t[100000];
int d[100000];

int main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    int from, to, ww;
    cin >> from >> to >> ww;
    g[from-1].push_back(to-1);
    w[from-1].push_back(ww);
  }

  for (int i = 0; i < n; i++)
  {
    int ki;
    cin >> ki;
    for (int j = 0; j < ki; j++)
    {
      int tt;
      cin >> tt;
      t[i].insert(tt);
    }
  }

  priority_queue< pair<int, int> > p;
  fill(d, d + n, INT_MAX);

  p.push(make_pair(0, 0));
  d[0] = 0;
  while (!p.empty())
  {
    int dc = p.top().first;
    int v  = p.top().second;
    p.pop();

    if (d[v] < dc) continue;

    for (int i = 0; i < g[v].size(); i++)
    {
      int to = g[v][i];
      int nt = d[v] + w[v][i];

      if (t[to].find(nt) != t[to].end())
	nt += 1;
      if (d[to] < nt)
	continue;
      d[to] = nt;
      p.push(make_pair(-nt, to));
    }
  }

  if (d[n-1] == INT_MAX)
    cout << -1;
  else
    cout << d[n-1];

  return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <cmath>
#include <limits.h>

typedef long long ll;

using namespace std;

vector<int> g[100000], w[100000];
set<int> t[100000];
ll d[100000];
int tt[100000];

int main()
{
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    int from, to, ww;
    cin >> from >> to >> ww;
    g[from-1].push_back(to-1);
    w[from-1].push_back(ww);
    g[to-1].push_back(from-1);
    w[to-1].push_back(ww);
  }

  for (int i = 0; i < n; i++)
  {
    int ki;
    cin >> ki;

    for (int j = 0; j < ki; j++)
      cin >> tt[j], t[i].insert(tt[j]);
    /*
    int st = tt[ki-1]+1;
    for (int j = ki-1; j >=0; j--)
    {
      if (j!= ki-1 && tt[j] != tt[j+1] - 1)
	st = tt[j] + 1;
      //cout << "# " << i <<" " <<tt[j] << " " << st << endl;
      t[i].insert(make_pair(tt[j], st));
    }   */
  }

  priority_queue< pair<ll, int> > p;
  fill(d, d + n, INT_MAX);

  p.push(make_pair(0, 0));
  d[0] = 0;
  while (!p.empty())
  {
    ll dc = abs(p.top().first);
    int v  = p.top().second;
    p.pop();

    //if (d[v] < dc) continue;

    dc = min(d[v], dc);

    while (t[v].count(dc)) dc++;

    for (int i = 0; i < g[v].size(); i++)
    {
      int to = g[v][i];

      ll nt = dc + w[v][i];

      if (d[to] < nt)
	continue;

      d[to] = nt;
      p.push(make_pair(-nt, to));
    }
  }

  if (d[n-1] == INT_MAX)
    cout << -1;
  else
    cout << d[n-1];

  return 0;
}


// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f3f3f3f3fLL
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
typedef __int64 LL;   //codeforces
//typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

#define CY 100005
#define E 200005
typedef LL typec;

struct re{
	int v, nxt;
	typec w;
}e[E];

int g[CY];
bool vis[CY];
typec dis[CY];
vector<typec> vec[CY];
queue<int> q;

int N, M, idx;

void init() {
	idx = 0;
	memset(g, -1, sizeof(g));
	for (int i = 0; i < CY; ++i) {
		vec[i].clear();
	}
}

void addedge(int u, int v, typec w) {
	e[idx].v = v;
	e[idx].w = w;
	e[idx].nxt = g[u]; g[u] = idx++;
}

void input(int n, int m) {
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, (typec)w);
		addedge(v, u, (typec)w);
	}
	for (int i = 1; i <= n; ++i) {
		int num, t;
		scanf("%d", &num);
		while (num--) {
			scanf("%d", &t);
			vec[i].push_back(t);
		}
	}
	//test
//	cout << idx << endl;
	//end
}

int F(typec v, int u, int lt, int rt) {
	int mid;
	while (lt < rt) {
		mid = (lt + rt) >> 1;
		if (vec[u][mid] >= v) rt = ~-mid;
		else lt = -~mid;
	}
	return lt;
}

typec spfa(int s, int t, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = s; i <= t; ++i) {
		dis[i] = INF;
	}
	dis[s] = 0;
	int u, v;
	while (!q.empty()) q.pop();
	q.push(s);
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = false;
		for (int i = g[u]; ~i; i = e[i].nxt) {
			v = e[i].v;
			typec time = dis[u] + e[i].w;
			int m = vec[u].size();
			int add = 0;
			int id = F(dis[u], u, 0, m - 1);
			for (int j = id; j < m; ++j) {
				if (vec[u][j] < dis[u]) continue;
				else {
					if (vec[u][j] == dis[u] || (j > 0 && vec[u][j] == vec[u][j - 1] + 1)) add++;
					else break;
				}
			}
			if (dis[v] > time + add) {
				dis[v] = time + add;
				if (v == t) continue;
				if (!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return dis[t] < INF ? dis[t] : -1;
}

void solve(int n, int m) {
	typec ans = spfa(1, n, n);
	cout << ans << endl;
}

int main(void) {
	while (2 == scanf("%d%d", &N, &M)) {
		init();
		input(N, M);
		solve(N, M);
	}
	return 0;
}


// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f3f3f3f3fLL
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
typedef __int64 LL;   //codeforces
//typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

#define CY 100005
#define E 200005
typedef LL typec;

struct re{
	int v, nxt;
	typec w;
}e[E];

int g[CY];
bool vis[CY];
typec dis[CY];
vector<typec> vec[CY];
queue<int> q;

int N, M, idx;

void init() {
	idx = 0;
	memset(g, -1, sizeof(g));
	for (int i = 0; i < CY; ++i) {
		vec[i].clear();
	}
}

void addedge(int u, int v, typec w) {
	e[idx].v = v;
	e[idx].w = w;
	e[idx].nxt = g[u]; g[u] = idx++;
}

void input(int n, int m) {
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, (typec)w);
		addedge(v, u, (typec)w);
	}
	for (int i = 1; i <= n; ++i) {
		int num, t;
		scanf("%d", &num);
		while (num--) {
			scanf("%d", &t);
			vec[i].push_back(t);
		}
	}
	//test
//	cout << idx << endl;
	//end
}

int F(typec v, int u, int lt, int rt) {
	int mid;
	while (lt < rt) {
		mid = (lt + rt) >> 1;
		if (vec[u][mid] >= v) rt = ~-mid;
		else lt = -~mid;
	}
	return lt;
}

typec spfa(int s, int t, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = s; i <= t; ++i) {
		dis[i] = INF;
	}
	dis[s] = 0;
	int u, v, id, m;
	while (!q.empty()) q.pop();
	q.push(s);
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = false;
		typec time = dis[u];
		m = vec[u].size();
		if (m > 0) {
			while (true) {
			//	id = F(time, u, 0, m - 1);
				id = lower_bound(vec[u].begin(), vec[u].end(), time) - vec[u].begin();
				if (id >= m || vec[u][id] != time) break;
				time++;
			}
		}
		for (int i = g[u]; ~i; i = e[i].nxt) {
			v = e[i].v;
			if (dis[v] > time + e[i].w) {
				dis[v] = time + e[i].w;
				if (v == t) continue;
				if (!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return dis[t] < INF ? dis[t] : -1;
}

void solve(int n, int m) {
	typec ans = spfa(1, n, n);
	cout << ans << endl;
}

int main(void) {
	while (2 == scanf("%d%d", &N, &M)) {
		init();
		input(N, M);
		solve(N, M);
	}
	return 0;
}


// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f3f3f3f3fLL
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
typedef __int64 LL;   //codeforces
//typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

#define CY 100005
#define E 200005
typedef LL typec;

struct re{
	int v, nxt;
	typec w;
}e[E];

int g[CY];
bool vis[CY];
typec dis[CY];
vector<typec> vec[CY];
queue<int> q;

int N, M, idx;

void init() {
	idx = 0;
	memset(g, -1, sizeof(g));
	for (int i = 0; i < CY; ++i) {
		vec[i].clear();
	}
}

void addedge(int u, int v, typec w) {
	e[idx].v = v;
	e[idx].w = w;
	e[idx].nxt = g[u]; g[u] = idx++;
}

void input(int n, int m) {
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, (typec)w);
		addedge(v, u, (typec)w);
	}
	for (int i = 1; i <= n; ++i) {
		int num, t;
		scanf("%d", &num);
		while (num--) {
			scanf("%d", &t);
			vec[i].push_back(t);
		}
	}
	//test
//	cout << idx << endl;
	//end
}

int F(typec v, int u, int lt, int rt) {
	int mid;
	while (lt < rt) {
		mid = (lt + rt) >> 1;
		if (vec[u][mid] >= v) rt = ~-mid;
		else lt = -~mid;
	}
	return lt;
}

typec spfa(int s, int t, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = s; i <= t; ++i) {
		dis[i] = INF;
	}
	dis[s] = 0;
	int u, v;
	while (!q.empty()) q.pop();
	q.push(s);
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = false;
		for (int i = g[u]; ~i; i = e[i].nxt) {
			v = e[i].v;
			int m = vec[u].size(), id;
			typec tmp = dis[u];
			if (m > 0) {
				while (true) {
					id = F(tmp, u, 0, m - 1);
					if (id == m || vec[u][id] != tmp) break;
					tmp++;
				}
			}
			if (dis[v] > tmp + e[i].w) {
				dis[v] = tmp + e[i].w;
				if (v == t) continue;
				if (!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return dis[t] < INF ? dis[t] : -1;
}

void solve(int n, int m) {
	typec ans = spfa(1, n, n);
	cout << ans << endl;
}

int main(void) {
	while (2 == scanf("%d%d", &N, &M)) {
		init();
		input(N, M);
		solve(N, M);
	}
	return 0;
}


// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f3f3f3f3fLL
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
typedef __int64 LL;   //codeforces
//typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

#define CY 100005
#define E 200005
typedef LL typec;

struct re{
	int v, nxt;
	typec w;
}e[E];

int g[CY];
bool vis[CY];
typec dis[CY];
vector<typec> vec[CY];
queue<int> q;

int N, M, idx;

void init() {
	idx = 0;
	memset(g, -1, sizeof(g));
	for (int i = 0; i < CY; ++i) {
		vec[i].clear();
	}
}

void addedge(int u, int v, typec w) {
	e[idx].v = v;
	e[idx].w = w;
	e[idx].nxt = g[u]; g[u] = idx++;
}

void input(int n, int m) {
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, (typec)w);
		addedge(v, u, (typec)w);
	}
	for (int i = 1; i <= n; ++i) {
		int num, t;
		scanf("%d", &num);
		while (num--) {
			scanf("%d", &t);
			vec[i].push_back(t);
		}
	}
	//test
//	cout << idx << endl;
	//end
}

int F(typec v, int u, int lt, int rt) {
	int mid;
	while (lt < rt) {
		mid = (lt + rt) >> 1;
		if (vec[u][mid] >= v) rt = ~-mid;
		else lt = -~mid;
	}
	return lt;
}

typec spfa(int s, int t, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = s; i <= t; ++i) {
		dis[i] = INF;
	}
	dis[s] = 0;
	int u, v;
	while (!q.empty()) q.pop();
	q.push(s);
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = false;
		typec time = dis[u];
		int m = vec[u].size();
		int add = 0;
		int id = F(dis[u], u, 0, m - 1);
		for (int j = id; j < m; ++j) {
			if (vec[u][j] < dis[u]) continue;
			else {
				if (vec[u][j] == dis[u] || (j > 0 && vec[u][j] == vec[u][j - 1] + 1)) add++;
				else break;
			}
		}
		for (int i = g[u]; ~i; i = e[i].nxt) {
			v = e[i].v;
			if (dis[v] > time + add + e[i].w) {
				dis[v] = time + add + e[i].w;
				if (v == t) continue;
				if (!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return dis[t] < INF ? dis[t] : -1;
}

void solve(int n, int m) {
	typec ans = spfa(1, n, n);
	cout << ans << endl;
}

int main(void) {
	while (2 == scanf("%d%d", &N, &M)) {
		init();
		input(N, M);
		solve(N, M);
	}
	return 0;
}


// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f3f3f3f3fLL
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
typedef __int64 LL;   //codeforces
//typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

#define CY 100005
#define E 200005
typedef LL typec;

struct re{
	int v, nxt;
	typec w;
}e[E];

int g[CY];
bool vis[CY];
typec dis[CY];
vector<typec> vec[CY];
queue<int> q;

int N, M, idx;

void init() {
	idx = 0;
	memset(g, -1, sizeof(g));
	for (int i = 0; i < CY; ++i) {
		vec[i].clear();
	}
}

void addedge(int u, int v, typec w) {
	e[idx].v = v;
	e[idx].w = w;
	e[idx].nxt = g[u]; g[u] = idx++;
}

void input(int n, int m) {
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, (typec)w);
		addedge(v, u, (typec)w);
	}
	for (int i = 1; i <= n; ++i) {
		int num, t;
		scanf("%d", &num);
		while (num--) {
			scanf("%d", &t);
			vec[i].push_back(t);
		}
	}
	//test
//	cout << idx << endl;
	//end
}

typec spfa(int s, int t, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = s; i <= t; ++i) {
		dis[i] = INF;
	}
	dis[s] = 0;
	int u, v;
	while (!q.empty()) q.pop();
	q.push(s);
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = false;
		for (int i = g[u]; ~i; i = e[i].nxt) {
			v = e[i].v;
			typec time = dis[u] + e[i].w;
			int m = vec[u].size();
			int add = 0;
			for (int j = 0; j < m; ++j) {
				if (vec[u][j] < dis[u]) continue;
				else {
					if (vec[u][j] == dis[u] || (j > 0 && vec[u][j] == vec[u][j - 1] + 1)) add++;
					else break;
				}
			}
			if (dis[v] > time + add) {
				dis[v] = time + add;
				if (v == t) continue;
				if (!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return dis[t] < INF ? dis[t] : -1;
}

void solve(int n, int m) {
	typec ans = spfa(1, n, n);
	cout << ans << endl;
}

int main(void) {
	while (2 == scanf("%d%d", &N, &M)) {
		init();
		input(N, M);
		solve(N, M);
	}
	return 0;
}


// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f3f3f3f3fLL
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
typedef __int64 LL;   //codeforces
//typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

#define CY 100005
#define E 200005
typedef LL typec;

struct re{
	int v, nxt;
	typec w;
}e[E];

int g[CY];
bool vis[CY];
typec dis[CY];
vector<typec> vec[CY];
queue<int> q;

int N, M, idx;

void init() {
	idx = 0;
	memset(g, -1, sizeof(g));
	for (int i = 0; i < CY; ++i) {
		vec[i].clear();
	}
}

void addedge(int u, int v, typec w) {
	e[idx].v = v;
	e[idx].w = w;
	e[idx].nxt = g[u]; g[u] = idx++;
}

void input(int n, int m) {
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, (typec)w);
		addedge(v, u, (typec)w);
	}
	for (int i = 1; i <= n; ++i) {
		int num, t;
		scanf("%d", &num);
		while (num--) {
			scanf("%d", &t);
			vec[i].push_back(t);
		}
	}
	//test
//	cout << idx << endl;
	//end
}

int F(typec v, int u, int lt, int rt) {
	int mid;
	while (lt < rt) {
		mid = (lt + rt) >> 1;
		if (vec[u][mid] >= v) rt = ~-mid;
		else lt = -~mid;
	}
	return lt;
}

typec spfa(int s, int t, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = s; i <= t; ++i) {
		dis[i] = INF;
	}
	dis[s] = 0;
	int u, v;
	while (!q.empty()) q.pop();
	q.push(s);
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = false;
		typec time = dis[u];
		int m = vec[u].size();
		int add = 0;
	//	int id = F(dis[u], u, 0, m - 1);
		for (int j = 0; j < m; ++j) {
			if (vec[u][j] < dis[u]) continue;
			else {
				if (vec[u][j] == dis[u] || (j > 0 && vec[u][j] == vec[u][j - 1] + 1)) add++;
				else break;
			}
		}
		for (int i = g[u]; ~i; i = e[i].nxt) {
			v = e[i].v;
			if (dis[v] > time + add + e[i].w) {
				dis[v] = time + add + e[i].w;
				if (v == t) continue;
				if (!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return dis[t] < INF ? dis[t] : -1;
}

void solve(int n, int m) {
	typec ans = spfa(1, n, n);
	cout << ans << endl;
}

int main(void) {
	while (2 == scanf("%d%d", &N, &M)) {
		init();
		input(N, M);
		solve(N, M);
	}
	return 0;
}


// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f3f3f3f3fLL
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
typedef __int64 LL;   //codeforces
//typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

#define CY 100005
#define E 200005
typedef LL typec;

struct re{
	int v, nxt;
	typec w;
}e[E];

int g[CY];
bool vis[CY];
typec dis[CY];
vector<typec> vec[CY];
queue<int> q;

int N, M, idx;

void init() {
	idx = 0;
	memset(g, -1, sizeof(g));
	for (int i = 0; i < CY; ++i) {
		vec[i].clear();
	}
}

void addedge(int u, int v, typec w) {
	e[idx].v = v;
	e[idx].w = w;
	e[idx].nxt = g[u]; g[u] = idx++;
}

void input(int n, int m) {
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, (typec)w);
		addedge(v, u, (typec)w);
	}
	for (int i = 1; i <= n; ++i) {
		int num, t;
		scanf("%d", &num);
		while (num--) {
			scanf("%d", &t);
			vec[i].push_back(t);
		}
	}
	//test
//	cout << idx << endl;
	//end
}

int F(typec v, int u, int lt, int rt) {
	int mid;
	while (lt <= rt) {
		mid = (lt + rt) >> 1;
		if (vec[u][mid] >= v) rt = ~-mid;
		else lt = -~mid;
	}
	return lt;
}

typec spfa(int s, int t, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = s; i <= t; ++i) {
		dis[i] = INF;
	}
	dis[s] = 0;
	int u, v, id, m;
	while (!q.empty()) q.pop();
	q.push(s);
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = false;
		typec time = dis[u];
		m = vec[u].size();
		if (m > 0) {
			while (true) {
				id = F(time, u, 0, m - 1);
			//	id = lower_bound(vec[u].begin(), vec[u].end(), time) - vec[u].begin();
				if (id >= m || vec[u][id] != time) break;
				time++;
			}
		}
		for (int i = g[u]; ~i; i = e[i].nxt) {
			v = e[i].v;
			if (dis[v] > time + e[i].w) {
				dis[v] = time + e[i].w;
				if (v == t) continue;
				if (!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return dis[t] < INF ? dis[t] : -1;
}

void solve(int n, int m) {
	typec ans = spfa(1, n, n);
	cout << ans << endl;
}

int main(void) {
	while (2 == scanf("%d%d", &N, &M)) {
		init();
		input(N, M);
		solve(N, M);
	}
	return 0;
}


// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f3f3f3f3fLL
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
typedef __int64 LL;   //codeforces
//typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

#define CY 100005
#define E 200005
typedef LL typec;

struct re{
	int v, nxt;
	typec w;
}e[E];

int g[CY];
bool vis[CY];
typec dis[CY];
vector<typec> vec[CY];
queue<int> q;

int N, M, idx;

void init() {
	idx = 0;
	memset(g, -1, sizeof(g));
	for (int i = 0; i < CY; ++i) {
		vec[i].clear();
	}
}

void addedge(int u, int v, typec w) {
	e[idx].v = v;
	e[idx].w = w;
	e[idx].nxt = g[u]; g[u] = idx++;
}

void input(int n, int m) {
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, (typec)w);
		addedge(v, u, (typec)w);
	}
	for (int i = 1; i <= n; ++i) {
		int num, t;
		scanf("%d", &num);
		while (num--) {
			scanf("%d", &t);
			vec[i].push_back(t);
		}
	}
	//test
//	cout << idx << endl;
	//end
}

int F(typec v, int u, int lt, int rt) {
	int mid;
	while (lt < rt) {
		mid = (lt + rt) >> 1;
		if (vec[u][mid] >= v) rt = ~-mid;
		else lt = -~mid;
	}
	return lt;
}

typec spfa(int s, int t, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = s; i <= t; ++i) {
		dis[i] = INF;
	}
	dis[s] = 0;
	int u, v;
	while (!q.empty()) q.pop();
	q.push(s);
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = false;
		for (int i = g[u]; ~i; i = e[i].nxt) {
			v = e[i].v;
			typec time = dis[u] + e[i].w;
			int m = vec[u].size();
			int add = 0;
			int id = F(dis[u], u, 0, m);
			for (int j = id; j < m; ++j) {
				if (vec[u][j] < dis[u]) continue;
				else {
					if (vec[u][j] == dis[u] || (j > 0 && vec[u][j] == vec[u][j - 1] + 1)) add++;
					else break;
				}
			}
			if (dis[v] > time + add) {
				dis[v] = time + add;
				if (v == t) continue;
				if (!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return dis[t] < INF ? dis[t] : -1;
}

void solve(int n, int m) {
	typec ans = spfa(1, n, n);
	cout << ans << endl;
}

int main(void) {
	while (2 == scanf("%d%d", &N, &M)) {
		init();
		input(N, M);
		solve(N, M);
	}
	return 0;
}


// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f3f3f3f3fLL
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
typedef __int64 LL;   //codeforces
//typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

#define CY 100005
#define E 200005
typedef LL typec;

struct re{
	int v, nxt;
	typec w;
}e[E];

int g[CY];
bool vis[CY];
typec dis[CY];
vector<typec> vec[CY];
queue<int> q;

int N, M, idx;

void init() {
	idx = 0;
	memset(g, -1, sizeof(g));
	for (int i = 0; i < CY; ++i) {
		vec[i].clear();
	}
}

void addedge(int u, int v, typec w) {
	e[idx].v = v;
	e[idx].w = w;
	e[idx].nxt = g[u]; g[u] = idx++;
}

void input(int n, int m) {
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, (typec)w);
		addedge(v, u, (typec)w);
	}
	for (int i = 1; i <= n; ++i) {
		int num, t;
		scanf("%d", &num);
		while (num--) {
			scanf("%d", &t);
			vec[i].push_back(t);
		}
	}
	//test
//	cout << idx << endl;
	//end
}

int F(typec v, int u, int lt, int rt) {
	int mid;
	while (lt < rt) {
		mid = (lt + rt) >> 1;
		if (vec[u][mid] >= v) rt = ~-mid;
		else lt = -~mid;
	}
	return lt;
}

typec spfa(int s, int t, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = s; i <= t; ++i) {
		dis[i] = INF;
	}
	dis[s] = 0;
	int u, v, id, m;
	while (!q.empty()) q.pop();
	q.push(s);
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = false;
		typec time = dis[u];
		m = vec[u].size();
		if (m > 0) {
			while (true) {
				id = F(time, u, 0, m - 1);
				if (id >= m || vec[u][id] != time) break;
				time++;
			}
		}
		for (int i = g[u]; ~i; i = e[i].nxt) {
			v = e[i].v;
			if (dis[v] > time + e[i].w) {
				dis[v] = time + e[i].w;
				if (v == t) continue;
				if (!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return dis[t] < INF ? dis[t] : -1;
}

void solve(int n, int m) {
	typec ans = spfa(1, n, n);
	cout << ans << endl;
}

int main(void) {
	while (2 == scanf("%d%d", &N, &M)) {
		init();
		input(N, M);
		solve(N, M);
	}
	return 0;
}


// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f3f3f3f3fLL
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
typedef __int64 LL;   //codeforces
//typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

#define CY 100005
#define E 200005
typedef LL typec;

struct re{
	int v, nxt;
	typec w;
}e[E];

int g[CY];
bool vis[CY];
typec dis[CY];
vector<typec> vec[CY];
queue<int> q;

int N, M, idx;

void init() {
	idx = 0;
	memset(g, -1, sizeof(g));
	for (int i = 0; i < CY; ++i) {
		vec[i].clear();
	}
}

void addedge(int u, int v, typec w) {
	e[idx].v = v;
	e[idx].w = w;
	e[idx].nxt = g[u]; g[u] = idx++;
}

void input(int n, int m) {
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, (typec)w);
		addedge(v, u, (typec)w);
	}
	for (int i = 1; i <= n; ++i) {
		int num, t;
		scanf("%d", &num);
		while (num--) {
			scanf("%d", &t);
			vec[i].push_back(t);
		}
	}
	//test
//	cout << idx << endl;
	//end
}

int F(typec v, int u, int lt, int rt) {
	int mid;
	while (lt < rt) {
		mid = (lt + rt) >> 1;
		if (vec[u][mid] >= v) rt = ~-mid;
		else lt = -~mid;
	}
	return lt;
}

typec spfa(int s, int t, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = s; i <= t; ++i) {
		dis[i] = INF;
	}
	dis[s] = 0;
	int u, v;
	while (!q.empty()) q.pop();
	q.push(s);
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = false;
		for (int i = g[u]; ~i; i = e[i].nxt) {
			v = e[i].v;
			typec time = dis[u];
			int m = vec[u].size();
			int id;
			if (m > 0) {
				while (true) {
					id = F(time, u, 0, m - 1);
					if (id >= m || vec[u][id] != time) break;
					time++;
				}
			}
			if (dis[v] > time + e[i].w) {
				dis[v] = time + e[i].w;
				if (v == t) continue;
				if (!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return dis[t] < INF ? dis[t] : -1;
}

void solve(int n, int m) {
	typec ans = spfa(1, n, n);
	cout << ans << endl;
}

int main(void) {
	while (2 == scanf("%d%d", &N, &M)) {
		init();
		input(N, M);
		solve(N, M);
	}
	return 0;
}


// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f3f3f3f3fLL
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
typedef __int64 LL;   //codeforces
//typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

#define CY 100005
#define E 200005
typedef LL typec;

struct re{
	int v, nxt;
	typec w;
}e[E];

int g[CY];
bool vis[CY];
typec dis[CY];
vector<typec> vec[CY];
queue<int> q;

int N, M, idx;

void init() {
	idx = 0;
	memset(g, -1, sizeof(g));
	for (int i = 0; i < CY; ++i) {
		vec[i].clear();
	}
}

void addedge(int u, int v, typec w) {
	e[idx].v = v;
	e[idx].w = w;
	e[idx].nxt = g[u]; g[u] = idx++;
}

void input(int n, int m) {
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, (typec)w);
		addedge(v, u, (typec)w);
	}
	for (int i = 1; i <= n; ++i) {
		int num, t;
		scanf("%d", &num);
		while (num--) {
			scanf("%d", &t);
			vec[i].push_back(t);
		}
	}
	//test
//	cout << idx << endl;
	//end
}

typec F(typec v, int u, int lt, int rt) {
	int mid;
	while (lt < rt) {
		mid = (lt + rt) >> 1;
		if (vec[u][mid] >= v) rt = ~-mid;
		else lt = -~mid;
	}
	return lt;
}

typec spfa(int s, int t, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = s; i <= t; ++i) {
		dis[i] = INF;
	}
	dis[s] = 0;
	int u, v;
	while (!q.empty()) q.pop();
	q.push(s);
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = false;
		for (int i = g[u]; ~i; i = e[i].nxt) {
			v = e[i].v;
			typec time = dis[u] + e[i].w;
			int m = vec[u].size();
			int add = 0;
			int id = F(dis[u], u, 0, m);
			for (int j = id; j < m; ++j) {
				if (vec[u][j] < dis[u]) continue;
				else {
					if (vec[u][j] == dis[u] || (j > 0 && vec[u][j] == vec[u][j - 1] + 1)) add++;
					else break;
				}
			}
			if (dis[v] > time + add) {
				dis[v] = time + add;
				if (v == t) continue;
				if (!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return dis[t] < INF ? dis[t] : -1;
}

void solve(int n, int m) {
	typec ans = spfa(1, n, n);
	cout << ans << endl;
}

int main(void) {
	while (2 == scanf("%d%d", &N, &M)) {
		init();
		input(N, M);
		solve(N, M);
	}
	return 0;
}


// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f3f3f3f3fLL
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
typedef __int64 LL;   //codeforces
//typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

#define CY 100005
#define E 200005
typedef LL typec;

struct re{
	int v, nxt;
	typec w;
}e[E];
struct P{
	int id;
	typec t;
};

int g[CY];
bool vis[CY];
typec dis[CY];
vector<int> vec[CY];
queue<P> q;

int N, M, idx;

void init() {
	idx = 0;
	memset(g, -1, sizeof(g));
	for (int i = 0; i < CY; ++i) {
		vec[i].clear();
	}
}

void addedge(int u, int v, typec w) {
	e[idx].v = v;
	e[idx].w = w;
	e[idx].nxt = g[u]; g[u] = idx++;
}

void input(int n, int m) {
	int u, v, w;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		addedge(u, v, (typec)w);
		addedge(v, u, (typec)w);
	}
	for (int i = 1; i <= n; ++i) {
		int num, t;
		scanf("%d", &num);
		while (num--) {
			scanf("%d", &t);
			vec[i].push_back(t);
		}
	}
	//test
//	cout << idx << endl;
	//end
}

typec spfa(int s, int t, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = s; i <= t; ++i) {
		dis[i] = INF;
	}
	dis[s] = 0;
	int u, v;
	P uu, vv;
	while (!q.empty()) q.pop();
	uu.id = s; uu.t = 0;
	q.push(uu);
	while (!q.empty()) {
		uu = q.front();
		u = uu.id;
		q.pop();
		vis[u] = false;
		for (int i = g[u]; ~i; i = e[i].nxt) {
			v = e[i].v;
			typec time = dis[u] + e[i].w;
			int m = vec[v].size();
			int add = 0;
			for (int j = 0; j < m; ++j) {
				if (vec[v][j] < time) continue;
				else {
					if (vec[v][j] == time || (j > 0 && vec[v][j] == vec[v][j - 1] + 1)) add++;
					else break;
				}
			}
			if (dis[v] > time + add) {
				dis[v] = time + add;
				if (v == t) continue;
				if (!vis[v]) {
					vis[v] = true;
					vv.id = v; vv.t = dis[v];
					q.push(vv);
				}
			}
		}
	}
	return dis[t] < INF ? dis[t] : -1;
}

void solve(int n, int m) {
	typec ans = spfa(1, n, n);
	cout << ans << endl;
}

int main(void) {
	while (2 == scanf("%d%d", &N, &M)) {
		init();
		input(N, M);
		solve(N, M);
	}
	return 0;
}