Given a connected undirected graph, tell if its minimum spanning tree is unique.

Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the following properties:
1. V' = V.
2. T is connected and acyclic.

Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E') of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E'.

Input

The first line contains a single integer t (1 <= t <= 20), the number of test cases. Each case represents a graph. It begins with a line containing two integers n and m (1 <= n <= 100), the number of nodes and edges. Each of the following m lines contains a triple (xi, yi, wi), indicating that xi and yi are connected by an edge with weight = wi. For any two nodes, there is at most one edge connecting them.

Output

For each input, if the MST is unique, print the total cost of it, or otherwise print the string 'Not Unique!'.

Sample Input

2
3 3
1 2 1
2 3 2
3 1 3
4 4
1 2 2
2 3 2
3 4 2
4 1 2

Sample Output

3
Not Unique! 思路:找次小生成树,如果权值相等则不唯一,用kruskal实现次小生成树
const int maxm = ;
const int maxn = ; struct edge {
int u, v, w;
edge(int _u=-, int _v=-, int _w=):u(_u), v(_v), w(_w){}
bool operator<(const edge &a) const {
return w < a.w;
}
};
vector<edge> Edge; int fa[maxm], T, N, M, tree[maxn], k; void init() {
Edge.clear();
for(int i = ; i <= N; ++i)
fa[i] = i;
k = ;
} int Find(int x) {
if(fa[x] == x)
return x;
return fa[x] = Find(fa[x]);
} void Union(int x, int y) {
x = Find(x), y = Find(y);
if(x != y) fa[x] = y;
} int main() {
scanf("%d", &T);
while(T--) {
int t1, t2, t3, u, v;
scanf("%d%d", &N, &M);
init();
int sum = ;
for(int i = ; i < M; ++i) {
scanf("%d%d%d", &t1, &t2, &t3);
Edge.push_back(edge(t1, t2, t3));
}
sort(Edge.begin(), Edge.end());
bool flag = true;
for(int i = ; i < M; ++i) {
u = Edge[i].u, v = Edge[i].v;
u = Find(u), v = Find(v);
if(u != v) {
sum += Edge[i].w;
Union(u,v);
tree[k++] = i;
}
}
for(int i = ; i < k; ++i) {
int cnt = , edgenum = ;
for(int t = ; t <= N; ++t)
fa[t] = t;
for(int j = ; j < M; ++j) {
if(j == tree[i]) continue;
u = Edge[j].u, v = Edge[j].v;
u = Find(u), v = Find(v);
if(u != v) {
cnt += Edge[j].w;
edgenum++;
Union(u,v);
}
}
if(cnt == sum && edgenum == N - ) {
flag = false;
break;
}
}
if(flag)
printf("%d\n", sum);
else printf("Not Unique!\n");
}
return ;
}

次小生成树博客:https://www.cnblogs.com/bianjunting/p/10829212.html

https://blog.csdn.net/niushuai666/article/details/6925258

注:这里的Max数组是记录从i到j节点中边权最大值(不是和),从其父节点与新连接的边中比较

												

最新文章

  1. Linux下的C Socket编程 -- server端的继续研究
  2. Go语言实现简单的一个静态WEB服务器
  3. scp报错:not a regular file,解决方法:加参数 -r
  4. 你可能不再需要Underscore
  5. Solaris系统管理(一)
  6. codeforces 677C C. Vanya and Label(组合数学+快速幂)
  7. Android TagFlowLayout完全解析 一款针对Tag的布局(转)
  8. git查看某个文件的修改历史
  9. css技巧之如何实现ul li边框重合
  10. BZOJ 1416: [NOI2006]神奇的口袋( 高精度 )
  11. cocos2dx进阶学习之CCApplication
  12. iOS程序 # 启动过程
  13. StringWriter/PrintWriter在Java输出异常信息中的作用
  14. Golang分布式爬虫:抓取煎蛋文章|Redis/Mysql|56,961 篇文章
  15. js继承与闭包(笔记)
  16. selenium基础框架的封装(Python版)
  17. [转帖]Zoom
  18. 可视化n次贝塞尔曲线及过程动画演示--大宝剑
  19. 转载:C++类内存分布
  20. 日期格式化(类似QQ邮箱中的邮件列表显示日期)

热门文章

  1. MySQL8.0 ROW_NUMBER、RANK、DENSE_RANK窗口函数 分组排序排名
  2. P1029最大公约数和最小公倍数
  3. PPT页面切换动画
  4. JavaScript 数字
  5. HTML标签,CSS简介
  6. aws-ec2-upload
  7. ABC154F - Many Many Paths
  8. redis 之redis-sentinel主从复制高可用
  9. 为什么不要在MySQL中使用UTF-8编码方式
  10. Oracle如何修改密码?如何解锁scott用户?