The Unique MST
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 23180   Accepted: 8235

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

  1. 2
  2. 3 3
  3. 1 2 1
  4. 2 3 2
  5. 3 1 3
  6. 4 4
  7. 1 2 2
  8. 2 3 2
  9. 3 4 2
  10. 4 1 2

Sample Output

  1. 3
  2. Not Unique!

Source

对于最小生成树(能够用kruskal和prime算法求得,在这里我是用kruskal求得,假设不会请自己百度。),边的权值的和最小称为最小生成树。

而次小生成树就是除了最小生成树外的最小生成树。并且全部的次小生成树都是通过最小生成树的换边得到的。

所以难点就是怎样换边。

对于怎样换边:

1.先求出最小生成树,值为x。

2.一一枚举加入不在生成树上的边(这时候一定形成了一个环)

3.寻找环上的(最小生成树上的边)权值最大值与你所加入不在生成树上的边的权值比較,所得到的差值为min。

因为是一一枚举加入边,min有多个,求出最小的哪一个,所以次小生成树就为x+min。

昨天尽管把这道题A了,但是看到讨论区的測试数据发现自己又一个没有过,然而却AC了。然后今天起床就来研究研究。

发现我的程序是在找最大值。但是假设一个环有分支,它还会去找分支里面的最大值。于是就又优化了一下。

用的优先队列。

先附上第一次做的代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <algorithm>
  4. using namespace std;
  5. struct node
  6. {
  7. int a,b,cost;
  8. }c[10005];
  9. int fa[105],tree[105][105],vis[10005],vis_tree[105];//vis数组是对m对数据的标记vis_tree是对最小生成树标记
  10. int n,m,max1;
  11. bool cmp(node x,node y)
  12. {
  13. if(x.cost<y.cost)
  14. return true;
  15. else
  16. return false;
  17. }
  18. int find(int x)//寻找根
  19. {
  20. if(fa[x]!=x) fa[x]=find(fa[x]);
  21. return fa[x];
  22. }
  23. void sec_tree(int a,int b)//查找生成树某条边的最大值(我在这里做的是错误的。假设形成的环有分支,也会查找)
  24. {
  25. vis_tree[a]=1;
  26. if(a==b)
  27. return ;
  28. for(int i=1;i<=n;i++)
  29. if(tree[a][i]&&!vis_tree[i])
  30. {
  31. if(max1<tree[a][i])
  32. max1=tree[a][i];
  33. sec_tree(i,b);
  34. }
  35. }
  36. int main()
  37. {
  38. int ncase;
  39. scanf("%d",&ncase);
  40. while(ncase--)
  41. {
  42. memset(vis,0,sizeof(vis));
  43. memset(tree,0,sizeof(tree));
  44. memset(&c,0,sizeof(&c));
  45. scanf("%d %d",&n,&m);
  46. for(int i=1;i<=n;i++)
  47. fa[i]=i;
  48. for(int i=0;i<m;i++)
  49. scanf("%d %d %d",&c[i].a,&c[i].b,&c[i].cost);
  50. sort(c,c+m,cmp);
  51. int sum=0;
  52. for(int i=0;i<m;i++)//kruskal算法求最小生成树
  53. {
  54. int x=find(c[i].a);
  55. int y=find(c[i].b);
  56. if(x!=y)
  57. {
  58. fa[x]=y,sum+=c[i].cost;
  59. tree[x][y]=tree[y][x]=c[i].cost;
  60. vis[i]=1;
  61. }
  62. }
  63. int flag=0;
  64. for(int i=0;i<m;i++)
  65. {
  66. if(!vis[i])//不在生成树中的边和形成的环的最大值比較。假设相等,MST不唯一
  67. {
  68. max1=-1;
  69. memset(vis_tree,0,sizeof(vis_tree));
  70. sec_tree(c[i].a,c[i].b);
  71. if(max1==c[i].cost)
  72. {
  73. flag=1;
  74. break;
  75. }
  76. }
  77. }
  78. if(!flag)
  79. printf("%d\n",sum);
  80. else
  81. printf("Not Unique!\n");
  82. }
  83. }

这是优化后的代码。凝视和上面一样。就一个地方不同:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <algorithm>
  4. #include <queue>
  5. using namespace std;
  6. struct node1
  7. {
  8. int a,b,cost;
  9. friend bool operator<(node1 x,node1 y )
  10. {
  11. return x.cost<y.cost;
  12. }
  13. };
  14. priority_queue<node1>s;
  15. struct node
  16. {
  17. int a,b,cost;
  18. }c[10005];
  19. int fa[105],tree[105][105],vis[10005],vis_tree[105];
  20. int n,m,max1,flag1;
  21. bool cmp1(node x,node y)
  22. {
  23. if(x.cost<y.cost)
  24. return true;
  25. else
  26. return false;
  27. }
  28. int find(int x)
  29. {
  30. if(fa[x]!=x) fa[x]=find(fa[x]);
  31. return fa[x];
  32. }
  33. void sec_tree(int a,int b)
  34. {
  35. node1 temp;
  36. vis_tree[a]=1;
  37. if(a==b)//假设找到a=b,标记一下
  38. {
  39. flag1=1;
  40. }
  41. for(int i=1;i<=n;i++)
  42. if(tree[a][i]&&!vis_tree[i])
  43. {
  44. temp.a=a,temp.b=i,temp.cost=tree[a][i];
  45. s.push(temp);
  46. if(!flag1)//就是在这里和上面不同,假设找不到a=b,那么就把曾经的恢复
  47. s.pop(),vis_tree[i]=0,sec_tree(i,b);
  48. }
  49. }
  50. int main()
  51. {
  52. int ncase;
  53. scanf("%d",&ncase);
  54. while(ncase--)
  55. {
  56. memset(vis,0,sizeof(vis));
  57. memset(tree,0,sizeof(tree));
  58. memset(&c,0,sizeof(&c));
  59. scanf("%d %d",&n,&m);
  60. for(int i=1;i<=n;i++)
  61. fa[i]=i;
  62. for(int i=0;i<m;i++)
  63. scanf("%d %d %d",&c[i].a,&c[i].b,&c[i].cost);
  64. sort(c,c+m,cmp1);
  65. int sum=0;
  66. for(int i=0;i<m;i++)
  67. {
  68. int x=find(c[i].a);
  69. int y=find(c[i].b);
  70. if(x!=y)
  71. {
  72. fa[x]=y,sum+=c[i].cost;
  73. tree[x][y]=tree[y][x]=c[i].cost;
  74. vis[i]=1;
  75. }
  76. }
  77. int flag=0;
  78. for(int i=0;i<m;i++)
  79. {
  80. if(!vis[i])
  81. {
  82. int flag1=0;
  83. while(!s.empty())
  84. s.pop();
  85. memset(vis_tree,0,sizeof(vis_tree));
  86. sec_tree(c[i].a,c[i].b);
  87. node1 temp;
  88. temp=s.top();
  89. if(temp.cost==c[i].cost)
  90. {
  91. flag=1;
  92. break;
  93. }
  94. }
  95. }
  96. if(!flag)
  97. printf("%d\n",sum);
  98. else
  99. printf("Not Unique!\n");
  100. }
  101. }

poj1679 The Unique MST(判定次小生成树)的更多相关文章

  1. POJ-1679 The Unique MST(次小生成树、判断最小生成树是否唯一)

    http://poj.org/problem?id=1679 Description Given a connected undirected graph, tell if its minimum s ...

  2. POJ1679 The Unique MST 【次小生成树】

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20421   Accepted: 7183 D ...

  3. POJ1679 The Unique MST【次小生成树】

    题意: 判断最小生成树是否唯一. 思路: 首先求出最小生成树,记录现在这个最小生成树上所有的边,然后通过取消其中一条边,找到这两点上其他的边形成一棵新的生成树,求其权值,通过枚举所有可能,通过这些权值 ...

  4. POJ1679 The Unique MST(次小生成树)

    可以依次枚举MST上的各条边并删去再求最小生成树,如果结果和第一次求的一样,那就是最小生成树不唯一. 用prim算法,时间复杂度O(n^3). #include<cstdio> #incl ...

  5. The Unique MST(次小生成树)

    Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 22335   Accepted: 7922 Description Give ...

  6. POJ1679The Unique MST(次小生成树)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 25203   Accepted: 8995 D ...

  7. poj 1679 The Unique MST【次小生成树】

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24034   Accepted: 8535 D ...

  8. POJ 1679:The Unique MST(次小生成树&amp;&amp;Kruskal)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19941   Accepted: 6999 D ...

  9. poj 1679 The Unique MST 【次小生成树】【模板】

    题目:poj 1679 The Unique MST 题意:给你一颗树,让你求最小生成树和次小生成树值是否相等. 分析:这个题目关键在于求解次小生成树. 方法是,依次枚举不在最小生成树上的边,然后加入 ...

  10. POJ 1679 The Unique MST (次小生成树)题解

    题意:构成MST是否唯一 思路: 问最小生成树是否唯一.我们可以先用Prim找到一棵最小生成树,然后保存好MST中任意两个点i到j的这条路径中的最大边的权值Max[i][j],如果我们能找到一条边满足 ...

随机推荐

  1. freeMark

    1. 什么是freemark       Freemaker是一个”模板引擎”,也可以说是一个基于模板技术的生成文本输出的一个通用工具 2.一般的用途: l 能用来生成任意格式的文本:HTML,XML ...

  2. C/C++(语句,数组)

    C语言语句: 两大选择,三大循环,四大跳转 两大跳转:if,switch 三大循环:for,while,do-while 四大跳转:break,continue,goto,return do-whil ...

  3. cf1089d Distance Sum

    题目大意 给一个有n个点,m条边的无向连通图,求所有点两两之间的最短路.$(2<=n<=10^5;n-1<=m<=n+42)$ solution 我们注意到$m-n+1$很小. ...

  4. last---显示用户最近登录信息

    last命令用于显示用户最近登录信息.单独执行last命令,它会读取/var/log/wtmp的文件,并把该给文件的内容记录的登入系统的用户名单全部显示出来. 语法 last(选项)(参数) 选项 - ...

  5. 负载均衡之lvs

    集群(cluster):将一组计算机软/硬件连接起来,高度紧密的协作完成计算工作,其中的单个计算机通常称为节点.负载均衡集群(Load Balancing):通过负载均衡器,将负载尽可能平均分摊处理. ...

  6. 【2017 Multi-University Training Contest - Team 3】RXD's date

    [Link]: [Description] [Solution] [NumberOf WA] 1 [Reviw] [Code] #include <bits/stdc++.h> using ...

  7. iOS 基于第三方QQ授权登录

    基于iOS实现APP的第三方QQ登陆.接入第三方SDK时的一个主要的步骤: 1,找到相关的开放平台.QQ互联平台,http://connect.qq.com/: 2,注冊成功后创建自己的APP.填写一 ...

  8. POJ--2516--Minimum Cost【最小费用最大流】

    链接:http://poj.org/problem?id=2516 题意:有k种货物,n个客户对每种货物有一定需求量,有m个仓库.每一个仓库里有一定数量的k种货物.然后k个n*m的矩阵,告诉从各个仓库 ...

  9. 终结者:借助pinyin4j相关jar包提取汉字的首字母

    import net.sourceforge.pinyin4j.PinyinHelper; import net.sourceforge.pinyin4j.format.HanyuPinyinCase ...

  10. 李笑来~执行力WWH

    什么是秘密 秘密是指只有极少数人知道的实用信息.这个实用信息可以为知道且懂得运用的人获得收益,这个收益可能包括钱.名声和快感. 什么是执行力 执行力=What + Why + How,即WWH 执行力 ...