//kruskal算法
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
typedef struct edge
{
int v,w,value;
}edge;
edge edges[101];
int father[101];
int childcounts[101];
int cmp(edge a,edge b)
{
return a.value<b.value;
}
int findfather(int x)
{
return father[x]==x?x:findfather(father[x]);
}
int unions(int x,int y)
{
int rootx=findfather(x);
int rooty=findfather(y);
if(rootx==rooty) return 0;
else if(childcounts[x]>=childcounts[y])
{
father[rooty]=rootx;
childcounts[x]+=childcounts[y];
}
else
{
father[rootx]=rooty;
childcounts[y]+=childcounts[x];
}
return 1;
}
int main()
{
int n,m,i,j,a,b,c,num,sum;
while(cin >> n >> m &&n)
{
num=0;sum=0;
for(i=1;i<=n;i++)
{
cin >> edges[i].v >> edges[i].w >> edges[i].value;
}
for(i=1;i<=m;i++)
{
father[i]=i;
childcounts[i]=1;
}
sort(edges+1,edges+n+1,cmp);
for(j=1;j<=n;j++)
{
if(unions(edges[j].v,edges[j].w))
{
num++;
sum+=edges[j].value;
}
}
if(num==m-1) cout << sum << endl;
else cout << '?' << endl;
}
return 0;
}