#include<bits/stdc++.h>
using namespace std;
const int MAXM = 7e4+5,MAXN = 3e3+5;
struct node
{
int p,w;
bool operator<(const node &X) const
{
return w>X.w;
}
};
struct e
{
int next,to,w;
} edge[MAXM];
int head[MAXN];
int a[MAXN][MAXN];
int n,m,cnt,u,v,w;
int aa[MAXN];
bool vis[MAXN];
long long d[MAXN],boom[MAXN];
int add(int u,int v,int w)
{
edge[++cnt].next = head[u];
head[u] = cnt;
edge[cnt].to = v;
edge[cnt].w = w;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1;i <= m;++i)
{
scanf("%d%d%d", &u, &v, &w);
add(u,v,w);
}
for(int i = 1;i <= n;++i)
{
scanf("%d", &a[i][0]);
for(int j = 1;j <= a[i][0]; ++j)
{
int b;
scanf("%d", &b);
a[i][b] = 1;
aa[i]++;
}
}
int s = 1;
priority_queue<node>q;
q.push({s,0});
memset(d,0x3f,sizeof(d));
d[s]=0;
while(!q.empty()) {
node now=q.top();
q.pop();
if(vis[now.p])
continue;
vis[now.p]=true;
for(int i = 1;i <= n;++i)
{
if(a[i][now.p])
{
a[i][now.p] = 0;
aa[i]--;
boom[i] = max(boom[i],d[now.p]);
if(!aa[i]) q.push({i,max(d[i],boom[i])});
}
}
for(int i=head[now.p];i>0;i=edge[i].next)
{
int t=edge[i].to;
if(d[t]>now.w + edge[i].w)
{
d[t]=now.w + edge[i].w;
if(!aa[t])
q.push({t,d[t]});
}
d[t] = max(d[t],boom[t]);
}
}
printf("%d", d[n]);
return 0;
}