#include <bits/stdc++.h>

#define whole(xs) xs.begin(),xs.end()

using namespace std;

namespace {

    typedef double real;
    typedef long long ll;

    template<class T> ostream& operator<<(ostream& os, const vector<T>& vs) {
        if (vs.empty()) return os << "[]";
        os << "[" << vs[0];
        for (int i = 1; i < int(vs.size()); i++) os << " " << vs[i];
        return os << "]";
    }
    template<class T> istream& operator>>(istream& is, vector<T>& vs) {
        for (auto it = vs.begin(); it != vs.end(); it++) is >> *it;
        return is;
    }

    struct Edge {
        int from, to;
        int cost;
        char firm;
        Edge() {}
        Edge(int from, int to, int cost, char firm) : from(from), to(to), cost(cost), firm(firm) {}
    };
    bool operator<(const Edge& a, const Edge& b) {
        if (a.cost == b.cost) return a.firm < b.firm;
        return a.cost < b.cost;
    }
    ostream& operator<<(ostream& os, const Edge& e) {
        return os << "Edge(" << e.from << "->" << e.to << " " << e.cost << " " << e.firm << ")";
    }

    int N, M, K;
    vector<Edge> es;
    bool input() {
        cin >> N >> M >> K;
        if (N == 0 && M == 0 && K == 0) return false;
        es.clear();
        for (int i = 0; i < M; i++) {
            int u, v, w; char l;
            cin >> u >> v >> w >> l;
            u--; v--;
            es.emplace_back(u, v, w, l);
        }
        return true;
    }

    struct UnionFind {
        int N;
        vector<int> P;
        UnionFind(int N) : N(N) {
            P.clear(); P.resize(N, -1);
        }
        int root(int x) {
            if (P[x] == -1) return x;
            return P[x] = root(P[x]);
        }
        int query(int x, int y) {
            return root(x) == root(y);
        }
        void merge(int x, int y) {
            x = root(x); y = root(y);
            if (x == y) return;
            P[x] = y;
        }
    };

    const int INF = 1<<20;

    int countA(int k) {
        vector<Edge> fs = es;
        for (int i = 0; i < M; i++) {
            Edge& f = fs[i];
            if (f.firm == 'A') f.cost += k;
        }
        sort(whole(fs));
        UnionFind uf(N);
        int count = 0;
        for (int i = 0; i < M; i++) {
            const Edge& f = fs[i];
            if (uf.query(f.from, f.to)) continue;
            uf.merge(f.from, f.to);
            if (f.firm == 'A') count++;
        }
        for (int i = 0; i < N; i++) {
            for (int j = i + 1; j < N; j++) {
                if (not uf.query(i, j)) throw(-1);
            }
        }
        return count;
    }

    int cost(int k) {
        vector<Edge> fs = es;
        for (int i = 0; i < M; i++) {
            Edge& f = fs[i];
            if (f.firm == 'A') f.cost += k;
        }
        int count = 0;
        sort(whole(fs));
        UnionFind uf(N);
        int ret = 0;
        for (int i = 0; i < M; i++) {
            const Edge& f = fs[i];
            if (uf.query(f.from, f.to)) continue;
            uf.merge(f.from, f.to);
            ret += f.cost;
        }
        return ret - K * k;
    }


    void solve() {
        int lb = -INF, ub = INF;
        int p, q;
        try {
            p = countA(lb); q = countA(ub);
        } catch (int e) {
            cout << -1 << endl;
            return;
        }
        if ( (p - K) * (q - K) > 0 ) {
            cout << -1 << endl;
            return;
        }
        while (lb + 1 < ub) {
            int mid = (lb + ub) / 2;
            //cerr << mid << " -> " << countA(mid) << endl;
            if (countA(mid) >= K) {
                lb = mid;
            } else {
                ub = mid;
            }
        }
        cout << cost(lb) << endl;
    }
}

int main() {
    while (input()) solve();
    return 0;
}

Measured memory_bytes: 3172