#include<cstdio> #include<algorithm> #define MAX 105 struct edge { int from,to; long long cost; }lm[MAX*MAX]; int N,M,father[MAX],i; bool cmp(edge a,edge b) { return a.cost<b.cost; } void init() { for(int i=1;i<=N;i++) father[i]=i; } int Find(int x) { if(x==father[x])return x; return father[x]=Find(father[x]); } bool Same(int x,int y) { return Find(x)==Find(y); } void unionset(int x,int y) { int u=Find(x),v=Find(y); if(u==v)return; father[u]=v; } long long kruskal() { long long res=0; std::sort(lm+1,lm+1+M,cmp); for(i=1;i<=M;i++) { if(Same(lm[i].from,lm[i].to))continue; unionset(lm[i].from,lm[i].to); res+=lm[i].cost; } return res; } int main() { while(scanf("%d%d",&M,&N)==2) { if(!M)break; init(); for(i=1;i<=M;i++) { scanf("%d%d%lld",&lm[i].from,&lm[i].to,&lm[i].cost); } long long res=kruskal(); for(i=1;i<=N;i++) if(!Same(i,1)) res=-1; if(res==-1) printf("? "); else printf("%lld ",res); } return 0; }