#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct edge {
int begin;
int end;
int weight;
};
const int maxn = 110;
int father[maxn];
edge e[maxn * maxn];
int map[maxn][maxn];
int n, m;
int mst_edge[maxn];
int find(int x) {
if (x == father[x]) {
return x;
}
father[x] = find(father[x]);
return father[x];
}
int kruscal(int count) { //使用kruscal算法来生成最小生成树并计算带权路径和
int i;
int sum = 0; //用sum来记录最小s生成树的边权和
memset(mst_edge,0,sizeof(mst_edge));
for (i = 1; i < maxn; ++i) {
father[i] = i;
}
int k = 0;
for (i = 1; i <= m && k < n - 1; ++i) { //枚举有序边集中的每一条边
int fx = find(e[i].begin);
int fy = find(e[i].end);
if (fx != fy) { //若第k条边的两个端点i,j 分别属于两颗不同的子树
father[fx] = fy; //则将节点i所在的子树并入节点j所在的子树中
sum += e[i].weight;
mst_edge[++k] = i;//***用来存储最小生成树中的边的序号
}
}
/**
* 以下代码是求解最小生成树唯一性问题的核心代码,其算法思想如下:
* 在生成的最小生成树的基础上,一次删除每一条边,生成次小生成树,
* 然后判断次小生成树的最小边权值是否==最小生成树的最小边权值,
* 如果相等,则证明最小生成树不唯一,否则证明所生成的最小生成树唯一
*
*/
int j;
for (i = 1; i <= n - 1; ++i) {
for (k = 1; k < maxn; ++k) {
father[k] = k;
}
int ans2 = 0, k2 = 0;
for (j = 1; j <= m; ++j) {
if (j == mst_edge[i]) {//模拟删除最小生成树的某一条边
continue;
}
int fx = find(e[j].begin);
int fy = find(e[j].end);
if (fx != fy) { //若第k条边的两个端点i,j 分别属于两颗不同的子树
father[fx] = fy; //则将节点i所在的子树并入节点j所在的子树中
ans2 += e[j].weight;
++k2;
}
}
if (k2 != n - 1) {//无法产生生成树
continue;
}
if (ans2 == sum) {//最小生成树不唯一
return -1;
}
}
return sum;
}
bool compare(const edge& a, const edge& b) {
return a.weight < b.weight;
}
//以上是用kruscal算法来解决问题的基本模板.....
int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &m);
int i, j;
for (i = 1; i <= m; ++i) {
scanf("%d%d%d", &e[i].begin, &e[i].end, &e[i].weight);
}
sort(e + 1, e + m + 1, compare); //kruscal算法要求边有序
int sum = kruscal(m);
if(sum == -1){
printf("Not Unique!\n");
}else{
printf("%d\n",sum);
}
}
return 0;
}