#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;
}