#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define DBG printf("this is a input\n")
#define fi first
#define se second
#define mk(a, b) make_pair(a,b)
#define p_queue priority_queue
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b) {
return a / gcd(a, b) * b;
}
int tot, n, fa[1000], e, k, sum;
map <string , int > ma;
struct node{
int u, v, w;
void init()
{
u = v = 0;
w = -1;
}
bool operator < (const node& no) const{
return w < no.w;
}
}edge[10000], dp[10000];
int f[1000][1000], cnt;
vector <int> ve[1000];
map <pair<int,int>, int> qm;
int findroot(int x)
{
if(fa[x] == x)
return x;
return fa[x] = findroot(fa[x]);
}
bool merge(int x, int y)
{
int fax = findroot(x);
int fay = findroot(y);
if(fax != fay) {
fa[fax] = fay;
return true;
}
return false;
}
void dfs(int u , int fa)
{
for(int i = 1 ; i <= tot ; i ++)
{
if(i == fa || !qm[mk(u,i)] || i == e)
continue;
if(dp[i].w == -1)
{
if(dp[u].w > f[u][i])
dp[i] = dp[u];
else
{
dp[i].u = u;
dp[i].v = i;
dp[i].w = f[u][i];
}
}
dfs(i,u);
}
}
void solve()
{
while(k > cnt)
{
k --;
int minn = 0 , index = 0;
for(int i = 1 ; i <= tot ; i ++)
dp[i].init();
dfs(e,-1); //dfs找出终点到各个顶点路径上的最大边,并维护出最大边的顶点编号
for(int i = 1 ; i <= tot ; i ++)
{
if(i != e && minn < dp[i].w - f[e][i] && f[e][i] != INF)
{
minn = dp[i].w - f[e][i];
index = i;
}
} //获得差值最大的结果
if(minn <= 0)
break;
sum -= minn;
qm[mk(dp[index].u,dp[index].v)] = qm[mk(dp[index].v,dp[index].u)] = 0;//删边
qm[mk(e,index)] = qm[mk(index,e)] = 1;//加边
}
}
int main(void)
{
cin>>n;
mem(f,INF);
for(int i = 1 ; i <= 2*n ; i ++)
fa[i] = i ;
string u, v;
int w;
//map编号
for(int i = 1 ; i <= n ; i ++)
{
cin>>u>>v>>w;
if(!ma[u])
ma[u] = ++ tot;
if(!ma[v])
ma[v] = ++ tot;
f[ma[v]][ma[u]] = f[ma[u]][ma[v]] = w;
edge[i].u = ma[u] , edge[i].v = ma[v] , edge[i].w = w;
}
//得出公园编号
e = ma["Park"];
cin>>k;
sort(edge+1,edge+1+n);
sum = 0;
//kruskal划分联通块(除了终点),得到最小生成森林
for(int i = 1; i <= n ; i ++)
{
int u = edge[i].u, v = edge[i].v;
if(u == e || v == e)
continue;
else
{
if(merge(u,v))
{
sum += edge[i].w;
qm[mk(u,v)] = qm[mk(v,u)] = 1; //使用过的边,构图
}
}
}
//联通块划分
for(int i = 1 ; i <= tot ; i ++)
ve[findroot(i)].push_back(i);
for(int i = 1 ; i <= tot ; i ++)
{
if(ve[i].size() && i != e)
{
cnt ++; //统计联通块数量
int minn = INF, index;
for(int j = 0 ; j < ve[i].size() ; j ++) //寻找每个联通块中的点与终点最小的边
{
if(minn > f[e][ve[i][j]])
{
minn = f[e][ve[i][j]];
index = ve[i][j];
}
}
sum += minn;//构成当前终点入度为cnt的最小生成树,不一定最优
qm[mk(index, e)] = qm[mk(e, index)] = 1;
}
}
solve();//是否存在更有生成树
printf("Total miles driven: %d\n",sum);
}