// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

using Int = long long;



struct Kruskal{



  struct UnionFind{

    Int n;

    vector<Int> r,p;

    UnionFind(){}

    UnionFind(Int sz):n(sz),r(sz,1),p(sz,0){iota(p.begin(),p.end(),0);}

    Int find(Int x){

      return (x==p[x]?x:p[x]=find(p[x]));

    }

    bool same(Int x,Int y){

      return find(x)==find(y);

    }

    void unite(Int x,Int y){

      x=find(x);y=find(y);

      if(x==y) return;

      if(r[x]<r[y]) swap(x,y);

      r[x]+=r[y];

      p[y]=x;

    }

  };

  

  struct edge{

    Int from,to;

    double cost;

    Int used;

    char color;

    edge(){}

    edge(Int from,Int to,double cost,char color):

      from(from),to(to),cost(cost),used(0),color(color){}

    bool operator<(const edge& e) const{

      return cost<e.cost;

    }

  };



  Int n;

  vector<edge> edges;



  Kruskal(){}

  Kruskal(Int sz):n(sz){}

  

  Int build(Int k=-1){

    sort(edges.begin(),edges.end());

    UnionFind uf(n+1);

    double res=0;

    Int cnt=0;

    for(Int i=0;i<(Int)edges.size();i++){

      edge &e=edges[i];

      if(!uf.same(e.from,e.to)){

	e.used=1;

	res+=e.cost;

	uf.unite(e.from,e.to);

	cnt++;

      }

    }

    if(cnt+1!=n) return -1;

    return res;

  }

};



signed main(){

  Int n,m,k;

  while(cin>>n>>m>>k,n){

    Kruskal kr(n);

    auto edges=kr.edges;

    for(Int i=0;i<m;i++){

      Int u,v,w;

      char c;

      cin>>u>>v>>w>>c;

      u--;v--;

      edges.emplace_back(u,v,w,c);

    }

    double ub=1e12,ans;

    auto check=[&](double x){

      x-=ub;

      kr=Kruskal(n);

      for(auto e:edges){

	if(x>0&&e.color=='A') e.cost+=x; 

	if(x<0&&e.color=='B') e.cost-=x; 

	kr.edges.emplace_back(e);

      }

      

      ans=kr.build();

      if(ans<0) return Int(-1);

      if(x>0) ans-=x*k;

      if(x<0) ans+=x*(n-1-k);

      

      Int res=0;

      for(auto e:kr.edges)

	res+=(e.used&&e.color=='A');

      return res;

    };

    double l=0,r=2*ub;

    if(check(l)<k||check(r)>k){

      cout<<-1<<endl;

      continue;

    }

    for(Int i=0;i<2000;i++){

      double m=(l+r)/2;

      if(check(m)>=k) l=m;

      else r=m;

    }

    check(l);

    cout<<(Int)ceil(ans)<<endl;

  }

  return 0;

}




// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

using namespace std;

using Int = long long;



struct UnionFind{

  Int n;

  vector<Int> r,p;

  UnionFind(){}

  UnionFind(Int sz):n(sz),r(sz,1),p(sz,0){iota(p.begin(),p.end(),0);}

  Int find(Int x){

    return (x==p[x]?x:p[x]=find(p[x]));

  }

  bool same(Int x,Int y){

    return find(x)==find(y);

  }

  void unite(Int x,Int y){

    x=find(x);y=find(y);

    if(x==y) return;

    if(r[x]<r[y]) swap(x,y);

    r[x]+=r[y];

    p[y]=x;

  }

};



struct Kruskal{



  

  struct edge{

    Int from,to,cost,used;

    char color;

    edge(){}

    edge(Int from,Int to,Int cost,char color):

      from(from),to(to),cost(cost),used(0),color(color){}

    bool operator<(const edge& e) const{

      return cost<e.cost;

    }

  };



  Int n;

  vector<edge> edges;



  Kruskal(){}

  Kruskal(Int sz):n(sz){}

  

  void add_edge(Int u,Int v,Int c,char d){

    edges.emplace_back(u,v,c,d);

  }



  void input(Int m,Int offset=0){

    Int a,b,c;

    char d;

    for(Int i=0;i<m;i++){

      cin>>a>>b>>c>>d;

      add_edge(a+offset,b+offset,c,d);

    }

  }

  

  Int build(){

    sort(edges.begin(),edges.end());

    UnionFind uf(n+1);

    Int res=0,cnt=0;

    for(auto &e:edges){

      if(!uf.same(e.from,e.to)){

	res+=e.cost;

	uf.unite(e.from,e.to);

	e.used=1;

	cnt++;

      }

    }

    //cout<<cnt<<" "<<res<<endl;

    if(cnt+1!=n) return -1;

    return res;

  }



  Int count(char c){

    Int res=0;

    for(auto& e:edges)

      if(e.used&&e.color==c) res++;

    return res;

  }

};





signed main(){

  Int n,m,k;

  while(cin>>n>>m>>k,n){

    //cout<<n<<" "<<m<<" "<<k<<endl;

    Kruskal kr(n);

    kr.input(m,-1);

    Int ans=kr.build();

    if(ans<0){

      cout<<-1<<endl;

      continue;

    }

    

    auto es=kr.edges;

    Int A=kr.count('A');

    Int B=kr.count('B');

    

    auto check=[&](char c,char d,Int i){

      Int res=-1;

      UnionFind uf(n);

      for(Int j=0;j<m;j++)

	if(i!=j&&es[j].used)

	  uf.unite(es[j].from,es[j].to);

      

      for(Int j=0;j<m;j++)

	if(es[j].color==d&&!es[j].used)

	  if(!uf.same(es[j].from,es[j].to))

	    if(res<0||es[j].cost<es[res].cost)

	      res=j;

      

      return res;

    };



    //cout<<A<<" "<<B<<endl;

    while(A>k){

      Int res=-1,idx=-1,idy=-1;

      for(Int i=0;i<m;i++){

	if(es[i].color!='A'||!es[i].used) continue;

	Int tmp=check('A','B',i);

	if(tmp<0) continue;

	if(res<0||es[tmp].cost-es[i].cost<res){

	  res=es[tmp].cost;

	  idx=i;idy=tmp;

	}

      }

      if(idx<0) break;

      es[idx].used=0;ans-=es[idx].cost;

      es[idy].used=1;ans+=es[idy].cost;

      A--;B++;

    }

    while(A<k){

      Int res=-1,idx=-1,idy=-1;

      for(Int i=0;i<m;i++){

	if(es[i].color!='B'||!es[i].used) continue;

	Int tmp=check('B','A',i);

	if(tmp<0) continue;

	if(res<0||es[tmp].cost-es[i].cost<res){

	  res=es[tmp].cost;

	  idx=i;idy=tmp;

	}

      }

      if(idx<0) break;

      es[idx].used=0;ans-=es[idx].cost;

      es[idy].used=1;ans+=es[idy].cost;

      A++;B--;

    }

    if(A!=k) cout<<-1<<endl;

    else cout<<ans<<endl;

  }

  return 0;

}




// Fastest known solution for this problem: