博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
The Unique MST
阅读量:6093 次
发布时间:2019-06-20

本文共 3702 字,大约阅读时间需要 12 分钟。

The Unique MST Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u

Submit

Description

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

23 31 2 12 3 23 1 34 41 2 22 3 23 4 24 1 2

Sample Output

3Not Unique! 也是最小生成树,问题是这个最小生成树的和,是不是可以由两条不同的路得到 问题就转换成了求次小生成树的问题,看两个是否相等
#include
#include
using namespace std;#define N 110#define INF 0xfffffffint n, maps[N][N], dist[N], pre[N], vis[N], Max[N][N], use[N][N];void init(){ memset(vis, 0, sizeof(vis)); // 判断下标是否已经在树上 memset(Max, 0, sizeof(Max)); // 求次小生成树的时候,要减去一条最大边加上一条最大边,还是保证每一个都联通,Max[i][j]数组存从i到j的已经在树上的联通路j到k, k到i两条路上边权值最大的一个 memset(pre, 0, sizeof(pre)); // pre存下标是通过哪个点连到路上的 memset(use, 0, sizeof(use)); // use从从i到j边权值是否被最小生成树用到 for(int i = 1; i <= n; i++) { dist[i] = 0; for(int j = 1; j <= n; j++) maps[i][j] = maps[j][i] = INF; maps[i][i] = 0; }} // 初始化int prim(){ int s = 1; vis[s] = 1; dist[s] = 0; int ans = 0; for(int i = 1; i <= n; i++) dist[i] = maps[i][s], pre[i] = s; // 从s点开始, s点先到树上 for(int i = 1; i < n; i++) { int index, Min = INF; for(int j = 1; j <= n; j++) if(!vis[j] && dist[j] < Min) Min = dist[j], index = j; // 找当前连到树上所需边权值最小的点 vis[index] = 1; ans += Min; // 最小值连树,边权值ans总和加 use[index][pre[index]] = use[pre[index]][index] = 1; // 表示这个边权值以被最小生成树用,求次小生成树的时候不能用啦 for(int j = 1; j <= n; j++) { if(vis[j] && index != j) Max[j][index] = Max[index][j] = max(Max[j][pre[index]], dist[index]);        // 把可能更新的全更新了,Max找最大的从j到index的路,在j到index的前一点的最大值和index连到pre【index】上找 if(!vis[j] && dist[j] > maps[j][index]) dist[j] = maps[j][index], pre[j] = index; // 更新最短路 } } return ans;}int MST(int sum){ int ans = INF; for(int i = 1; i <= n; i++) { for(int j = i+1; j <= n; j++) { if(!use[i][j] && maps[i][j] != INF) ans = min(ans, sum - Max[i][j] + maps[i][j]); // 找次小生成树,减去最小生成树上i到j最大的边,加上i到j的边权值,联通i,j。min是找较小的 } } return ans;}int main(){ int t, m, x, y, w; cin >> t; while(t--) { cin >> n >> m; init(); while(m--) { cin >> x >> y >> w; maps[x][y] = maps[y][x] = w; } int num1 = prim(); int num2 = MST(num1); if(num1 != num2) cout << num1 << endl; // 如果最小生成树和次小生成树不等,就输出唯一的最小生成树的边权值之和,否则输出Not Unique! else cout << "Not Unique!" << endl; } return 0;}

 

转载于:https://www.cnblogs.com/Tinamei/p/4680237.html

你可能感兴趣的文章
java注解【转】
查看>>
Oracle表分区
查看>>
centos 下安装g++
查看>>
调试、手机-手游开发知识(三)--NDK联机调试-by小雨
查看>>
嵌入式,代码调试----GDB扫盲
查看>>
类斐波那契数列的奇妙性质
查看>>
配置设置[Django]引入模版之后报错Requested setting TEMPLATE_DEBUG, but settings are not configured....
查看>>
下一步工作分配
查看>>
Response. AppendHeader使用大全及文件下载.net函数使用注意点(转载)
查看>>
Wait Functions
查看>>
代码描述10313 - Pay the Price
查看>>
jQuery最佳实践
查看>>
centos64i386下apache 403没有权限访问。
查看>>
下划线的学习5
查看>>
Spring Data JPA教程, 第六部分: Sorting(未翻译)
查看>>
重建二叉树
查看>>
企业管理软件开发之九 以数据绑定为基础的控件只读,创建时可写,必须大写,必须小写的原理与实现...
查看>>
批处理清理VS工程目录(递归删除Debug, Release, ipch目录及*.sdf文件)
查看>>
在Windows中监视IO性能
查看>>
thrift之TTransport层的缓存传输类TBufferedTransport和缓冲基类TBufferBase
查看>>