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

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
struct Edge{
    int dst, cap, rev;
};
typedef vector<Edge> Node;
typedef vector<Node> Graph;
struct Dinic{
    Graph G;
    vector<int> level;
    vector<int> iter;
    
    Dinic(int N) : G(N), level(N), iter(N) {}

    void bfs(int s){
        level.assign(G.size(), -1);
        queue<int> que;
        que.push(s);
        level[s] = 0;
        while(!que.empty()){
            int v = que.front(); que.pop();
            for(const auto& e : G[v]){
                if(e.cap > 0 && level[e.dst] < 0){
                    level[e.dst] = level[v] + 1;
                    que.push(e.dst);
                }
            }
        }
    }

    int dfs(int v, int t, int f){
        if(v == t) return f;
        for(int& i = iter[v]; i < G[v].size(); i++){
            Edge& e = G[v][i];
            if(e.cap > 0 && level[v] < level[e.dst]){
                int d = dfs(e.dst, t, min(f, e.cap));
                if(d > 0){
                    e.cap -= d;
                    G[e.dst][e.rev].cap += d;
                    return d;
                }
            }
        }
        return 0;
    }

    void add_edge(int src, int dst, int cap){
        G[src].push_back({dst, cap, (int)G[dst].size()});
        G[dst].push_back({src, 0, (int)G[src].size() - 1});
    }

    int max_flow(int src, int dst){
        int flow = 0;
        while(true){
            bfs(src);
            if(level[dst] < 0) break;
            iter.assign(G.size(), 0);
            while(true){
                int f = dfs(src, dst, INF);
                if(f <= 0) break;
                flow += f;
            }
        }
        return flow;
    }
};

// Ford-Fulkerson
struct FordFulkerson{
    Graph G;
    vector<bool> used;
    FordFulkerson(int N) : G(N) {}

    void add_edge(int src, int dst, int cap){
        G[src].push_back({dst, cap, (int)G[dst].size()});
        G[dst].push_back({src, 0, (int)G[src].size() - 1});
    }

    int max_flow(int src, int dst) {
        int flow = 0;
        while(true) {
            used.assign(G.size(), false);
            int f = dfs(src, dst, INT_MAX);
            if(f == 0) break;
            flow += f;
        }
        return flow;
    }

    int dfs(int v, int t, int f) {
        if(v == t) return f;
        used[v] = true;
        for(Edge& e : G[v]) {
            if(e.cap > 0 && !used[e.dst]) {
                int d = dfs(e.dst, t, min(f, e.cap));
                if(d > 0) {
                    e.cap -= d;
                    G[e.dst][e.rev].cap += d;
                    return d;
                }
            }
        }
        return 0;
    }
};


int main(){
    int N, M, L;
    while(cin >> N >> M >> L){
        int dist[110][110] = {};
        REP(i, N) REP(j, N) dist[i][j] = (i != j ? INF : 0);
        REP(i, M){
            int a, b, c; cin >> a >> b >> c;
            a--; b--;
            dist[a][b] = dist[b][a] = c;
        }
        REP(k, N) REP(i, N) REP(j, N) dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
        int S = 2 * N;
        int D = S + 1;
        FordFulkerson d(D + 1);
        REP(i, N){
            int P; cin >> P;
            d.add_edge(S, i, P);
        }
        REP(i, N){
            int K; cin >> K;
            d.add_edge(N + i, D, K);
        }
        REP(i, N) REP(j, N) if(dist[i][j] < L) d.add_edge(i, N + j, INF);
        int ans = d.max_flow(S, D);
        cout << ans << endl;
    }
    return 0;
}