#include <vector>#include <list>#include <map>#include <set>#include <queue>#include <deque>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <ctime>#include <cstring>#include <memory.h>using namespace std;/* * poj1639 AC * K度最小生成树 * 1. 求出除去V0,其他每个森林的最小生成树(除去V0后,其他的点不一定都是连通的)。 * 2. 在每个森林中找出与V0距离最近的点,并与V0相连(此时即为一棵生成树,这棵 * 生成树的根结点为V0,即在与V0相连时,要修改前驱数组pre[])。 * 3. 循环 (度数 – 森林数)次,每次找到g[0][i] – MV[i]最小的i结点,其中MV[i] * 为Vi到V0的路径上不与V0相连的边的最大权值。 * 如果g[0][i] – MV[i] >= 0说明已经是最优解了,退出。 * 否则加入g[0][i]这条边,删去Vi到V0的路径上不与V0相连的最大权值的边。 * * 如何快速找到Vi到V0的路径上不与V0相连的边的最大权值? * MV[x] = max(MV[father],edge[i].c) (edge[i]为x到father的边,递推可得) * */int N,S,T;map<string,int> hash;struct EDGE{ int u,v,c,nm;}edge[1000];int head[25],next[1000],tot,goal;struct cmp{ bool operator()(const EDGE &t1,const EDGE &t2) { return t1.c>t2.c; }};void addedge(int x,int y,int val){ edge[tot].u = x,edge[tot].v = y,edge[tot].c = val,edge[tot].nm = tot; next[tot] = head[x],head[x] = tot++;}priority_queue<EDGE,vector<EDGE>,cmp> heap;bool vis[25],sel_e[1000];int solve(int x,int TT){ int E,nn,SUM; while(!heap.empty()) heap.pop(); for(int i=head[x];i!=-1;i=next[i]) if(edge[i].v!=goal) heap.push(edge[i]); vis[x] = true,SUM = E = 0; while(E<TT-1) { EDGE e = heap.top(); heap.pop(); if(vis[e.v]) continue; sel_e[e.nm] = sel_e[e.nm^1] = true; E++,SUM += e.c; nn = e.v,vis[e.v] = true; for(int i=head[nn];i!=-1;i=next[i]) if(edge[i].v!=goal && !vis[edge[i].v]) heap.push(edge[i]); } return SUM;}int col[25],C;int dfs(int x){ col[x] = C; int ss = 1; for(int i=head[x];i!=-1;i=next[i]) if(edge[i].v!=goal && !col[edge[i].v]) ss += dfs(edge[i].v); return ss;}int MV[25],ne[25];void dfs_V(int x,int f){ for(int i=head[x];i!=-1;i=next[i]) if(sel_e[i] && edge[i].v!=f && edge[i].v!=goal) { if(MV[x]>edge[i].c) { MV[edge[i].v] = MV[x]; ne[edge[i].v] = ne[x]; }else { MV[edge[i].v] = edge[i].c; ne[edge[i].v] = i; } dfs_V(edge[i].v,x); }}int main(){ scanf("%d",&N); char st[20],en[20]; T = tot = goal = 0; memset(head,-1,sizeof(head)); hash.clear(); for(int i=1;i<=N;i++) { int k; scanf("%s%s%d",st,en,&k); if(!hash.count(st)) hash[st] = ++T; if(!hash.count(en)) hash[en] = ++T; if(!goal) { if(!strcmp(st,"Park")) goal = hash[st]; if(!strcmp(en,"Park")) goal = hash[en]; } addedge(hash[st],hash[en],k); addedge(hash[en],hash[st],k); } scanf("%d",&S); int ans = 0; C = 0; memset(vis,false,sizeof(vis)); memset(col,0,sizeof(col)); memset(sel_e,false,sizeof(sel_e)); for(int i=1;i<=T;i++) if(i!=goal && !col[i]) ++C,ans += solve(i,dfs(i)); int mi[25],me[25]; memset(mi,-1,sizeof(mi)); for(int i=head[goal];i!=-1;i=next[i]) { int k = edge[i].v; if(mi[col[k]]==-1 || edge[i].c<mi[col[k]]) { mi[col[k]] = edge[i].c; me[col[k]] = i; } } for(int i=1;i<=C;i++) ans += mi[i],sel_e[me[i]] = sel_e[me[i]^1] = true; memset(MV,0,sizeof(MV)); for(int i=head[goal];i!=-1;i=next[i]) if(sel_e[i] && edge[i].v!=goal) dfs_V(edge[i].v,goal); for(int i=1;i<=S-C;i++) { int mm = 100000000,xx,ee,ww; for(int j=head[goal];j!=-1;j=next[j]) if(!sel_e[j] && (mm==100000000 || mm>edge[j].c-MV[edge[j].v])) { mm = edge[j].c-MV[edge[j].v]; xx = edge[j].v,ee = j,ww = ne[edge[j].v]; } if(mm>=0) break; ans += mm; sel_e[ee] = sel_e[ee^1] = true; sel_e[ww] = sel_e[ww^1] = false; MV[xx] = 0; dfs_V(xx,goal); } printf("Total miles driven: %d\n",ans); return 0;}