use std::hash::Hash;
use std::collections::hash_set::Iter;
use std::rc::Rc;
use std::ops::DivAssign;
use std::ops::MulAssign;
use std::ops::SubAssign;
use std::collections::BinaryHeap;
use std::str::FromStr;
use std::collections::HashSet;
use std::collections::BTreeMap;
use std::fmt::Display;
use std::ops::Neg;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Add;
use std::ops::{AddAssign, Sub};
use std::cmp::max;
use std::collections::VecDeque;
use std::cmp::min;
use std::collections::{HashMap, BTreeSet};
use std::cmp::Ordering;
use std::fmt::Debug;

fn read_line() -> String {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).expect("No Line");
    buffer.trim().to_owned()
}
fn read_lines<T: std::str::FromStr>(count: usize) -> Vec<T> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(buffer.trim().parse().ok().expect("Can't Parse"));
        buffer.clear();
    }
    vec
}
fn read_tabulate<R, T: Fn(&str)->R> (count: usize, transformer: T) -> Vec<R> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(transformer(buffer.trim()));
        buffer.clear();
    }
    vec
}
fn read_value<T: std::str::FromStr>() -> T {
    read_line().trim().parse().ok().unwrap()
}
fn read_values<T: std::str::FromStr>() -> Vec<T> {
    read_line().trim().split_whitespace().map(|x| x.parse().ok().expect("Can't Parse")).collect::<Vec<T>>()
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
macro_rules! read_map {
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
}
macro_rules! read {
    (mut $ident: ident: String) => {
        let mut $ident = read_value::<String>();
    };
    ($ident: ident: String) => {
        let $ident = read_value::<String>();
    };
    (mut $ident: ident: [$ty:ty]) => {
        let mut $ident = read_values::<$ty>();
    };
    ($ident: ident: [$ty:ty]) => {
        let $ident = read_values::<$ty>();
    };
    (mut $ident: ident: [[$ty:ty]; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    ($ident: ident: [[$ty:ty]; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$ty:ty; $size:expr]) => {
        let mut $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$ty:ty; $size:expr]) => {
        let $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    ($($token: tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        read_from_iter!(iter; $($token)*);
    };
}
macro_rules! read_from_iter {
    ($iter:expr; mut $ident:ident:$ty:ty, $($rest:tt)*) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; $ident:ident:$ty:ty, $($rest:tt)*) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; mut $ident:ident:$ty:ty) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter:expr; $ident:ident:$ty:ty) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter: expr; ) => {};
}
struct KeyValue<K, V> {
    key: K,
    value: V
}
impl <K: PartialOrd, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}
impl <K: PartialOrd, V> Eq for KeyValue<K, V> {}
impl <K: PartialOrd, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.key.partial_cmp(&other.key)
    }
}
impl <K: PartialOrd, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.key.partial_cmp(&other.key).ok_or("Can't Compare").unwrap()
    }
}
#[derive(Eq, PartialEq)]
struct Rev<T: Ord>(T);
impl <T: std::cmp::Ord> PartialOrd for Rev<T> {
    fn partial_cmp(&self, rhs: &Rev<T>) -> std::option::Option<std::cmp::Ordering> { 
        rhs.0.partial_cmp(&self.0)
    }
}
impl <T: Ord> Ord for Rev<T> {
    fn cmp(&self, rhs: &Self) -> std::cmp::Ordering { 
        rhs.0.cmp(&self.0)
    }
}
#[derive(Copy, Clone)]
struct Bridge {
    a: usize, b: usize, cost: i32, provider: usize
}
impl Bridge {
    fn opposit(&self, side: usize) -> usize {
        assert_eq!(true, self.a == side || self.b == side);
        if self.a == side {
            self.b
        }else {
            self.a
        }
    }
}
#[derive(Clone, Debug)]
struct UnionFind {
    parent: Vec<i32>
}
impl UnionFind {
    fn new(size: usize) -> UnionFind {
        UnionFind{parent: vec![-1; size]}
    }
    fn find(&mut self, a: usize) -> usize {
        if self.parent[a] < 0 {
            a
        }else {
            let p = self.parent[a] as usize;
            let root = self.find(p);
            self.parent[a] = root as i32;
            root
        }
    }
    fn same(&mut self, a: usize, b: usize) -> bool {
        self.find(a) == self.find(b)
    }
    fn unite(&mut self, mut a: usize, mut b: usize) -> bool {
        a = self.find(a);
        b = self.find(b);
        if a == b {return false;}
        if self.parent[a] < self.parent[b] {
            self.parent[a] += self.parent[b];
            self.parent[b] = a as i32;
        }else {
            self.parent[b] += self.parent[a];
            self.parent[a] = b as i32;
        }
        true
    }
}
fn max_count_of_provider(size: usize, target_provider: usize, edges: &Vec<Bridge>) -> usize {
    let mut uft = UnionFind::new(size);
    let mut count = 0;
    let mut provider_count = 0;
    for e in edges {
        if e.provider == target_provider {
            if uft.unite(e.a, e.b) {
                count += 1;
                provider_count += 1;
            }
        }
    }
    for e in edges {
        if e.provider != target_provider {
            if uft.unite(e.a, e.b) {
                count += 1;
            }
        }
    }
    if count + 1 == size { provider_count } else {0}
}
fn make_min_cost_tree(size: usize, edges: &Vec<Bridge>, bias: i32) -> Option<(usize, i32)> {
    let mut heap = BinaryHeap::new();
    let mut uft = UnionFind::new(size);
    let mut count = 0;
    let mut provider0_count = 0;
    let mut sum_cost = 0;
    for i in 0 .. edges.len(){
        let e = edges[i];
        if e.provider == 0 {
            heap.push(Rev(KeyValue{key: ((e.cost + bias) << 1) + 1, value: i}));
        }else {
            heap.push(Rev(KeyValue{key: e.cost << 1, value: i}));
        }
    }
    while let Some(Rev(KeyValue{key: cost, value: i})) = heap.pop() {
        let e = edges[i];
        if uft.unite(e.a, e.b) {
            count += 1;
            if e.provider == 0 {
                provider0_count += 1;
            }
            sum_cost += cost >> 1;
        } 
    }
    if count + 1 == size {
        Some((provider0_count, sum_cost))
    }else {
        None
    }
}
fn calc_min_cost(size: usize, k: usize, edges: Vec<Bridge>) -> Option<i32> {
    if max_count_of_provider(size, 0, &edges) < k || max_count_of_provider(size, 1, &edges) < size - 1 - k{ return  None; }
    let mut min = size as i32 * -200;
    let mut max = size as i32 * 200;
    while min < max {
        let mid = (min + max) >> 1;
        let count = if let Some((count, _)) = make_min_cost_tree(size, &edges, mid) {count} else {return None};
        if count < k {
            max = mid;
        }else {
            min = mid + 1;
        }
    }
    if let Some((_, cost)) = make_min_cost_tree(size, &edges, max) {
        Some(cost - max * k as i32)
    }else {
        None
    }
}
fn main() {
    loop {
        read!(n: usize, m: usize, k: usize);
        if n == 0 && m == 0 && k == 0 {break;}
        read_map!(edges: [{
            read!(u: usize, v: usize, w: i32, l: String);
            Bridge{a: u - 1, b: v - 1, cost: w, provider: if l == "A" {0}else {1}}
        }; m]);
        println!("{}", calc_min_cost(n, k, edges).unwrap_or(-1));
    }
}



Measured memory_bytes: 5052