#include <climits>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct Edge{
int to,w;
Edge(int x, int y): to(x), w(y) {};
};
struct Point{
int p,d;
Point(int x, int y): p(x), d(y) {};
bool operator < (const Point &po) const{
return d > po.d;//用大根堆实现小根堆
}
};
const int N = 610;
const int INF = INT_MAX;
int st[N];
int dist[N];
vector<Edge> g[N];//邻接表
void init(int n){
for(int i=1;i<=n;i++){
dist[i]=INF;
g[i].clear();
}
dist[1]=0;
}
/*dijie什么时候确定一条边是要加入到最小生成树里呢?:
在小根堆弹出对头元素时,加入的边是对头元素与最小生成树某一结点的边。
限制条件:选入的边,只能从阵营1到阵营2,不能存在从阵营2到阵营1
因为:不能从阵营2到阵营1,而起点在阵营1,终点在阵营2,故只选择了一条从阵营1到阵营2的边。
*/
void dijie(int n){
priority_queue<Point> heap;
heap.push(Point(1,0));
while(heap.size()){
Point t = heap.top();
heap.pop();
int u = t.p;
for(int i=0;i<g[u].size();i++){
int v = g[u][i].to;
int l = g[u][i].w;
if(st[v]==1&&st[u]==2)continue;
if(dist[u]+l<dist[v]){
dist[v]=dist[u]+l;
heap.push(Point(v,dist[v]));
}
}
}
return;
}
int main(){
int n;
while(cin>>n){
if(!n)break;
init(n);
int m;
cin>>m;
while(m--){
int a,b,w;
cin>>a>>b>>w;
g[a].push_back(Edge(b,w));
g[b].push_back(Edge(a,w));
}
for(int i=1;i<=n;i++){
cin>>st[i];
}
dijie(n);
int ans = dist[2]==INF? -1:dist[2];
cout<<ans<<endl;
}
return 0;
}