题意:求解最小生成树的权值是否唯一,即要我们求次小生成树的权值
两种方法求最小生成树,一种用prim算法, 一种用kruskal算法

一:用prim算法

对于给定的图,我们可以证明,次小生成树可以由最小生成树变换一边得到。 那么我们可以如下求给定图的次小生成树。首先,我们用prime算法求出图的最小生成树, 在这个过程中记录每条边是否用过,以及两个点之间最短路径上的最大权值F[i,j]

F[i,j]可以如此求得,当加入点u的时候,并且u的父结点是v 那么对于已经在生成树中的节点x F[x,u] = max(F[x,v],w[u][v]),那么我么就可以用Prime算法一样的时间复杂度来求出图的次小生成树。

参考链接:http://blog.csdn.net/lyg_wangyushi/article/details/4371734

#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <string>
#include <queue>
using namespace std; const int INF=0x3f3f3f3f;
int n,m;
int ans1,ans2;
int w[][];
int dis[];
int pre[];
int vis[];
int use[][]; //use[i][j]=1表示边(i,j)在最小生成树里,=0则不在
int f[][]; //f[u][v]表示结点u到结点v的最短路径上边的最大值(即最大边的值)
vector<int> son[]; //son[i]存储的是与i连接的端点 void init() {
memset(pre,,sizeof(pre));
memset(dis,INF,sizeof(dis));
memset(vis,,sizeof(vis));
memset(f,,sizeof(f));
memset(use,,sizeof(use));
}
//求最小生成树
int solve_MST() {
init();
vector<int> node;
int s=,counts=,ans=,tmp,k;
dis[s]=;
pre[s]=s; node.push_back(s); //一开始dis都赋值为INF,所以为了减少一点点遍历的时间,node存储的是dis不为INF的点
while() {
tmp=INF;
for(int i=; i<node.size(); i++) {
int v=node[i];
if(!vis[v]&& dis[v]<tmp) {
tmp=dis[v];
k=v; //k即为在没有进入最小生成树的点中到树的距离(dis[k])最小的点。
}
}
if(tmp==INF)
break;
use[k][pre[k]]=use[pre[k]][k]=; for(int i=;i<=n;i++){
if(vis[i]){
f[i][k]=f[k][i]=max(f[i][pre[k]],w[k][pre[k]]);
f[i][k]=f[k][i]=max(f[pre[k]][i],w[k][pre[k]]);
}
}
ans+=tmp;
vis[k]=; for(int i=; i<son[k].size(); i++) {
int v=son[k][i];
if(!vis[v] && w[k][v]<dis[v]) {
dis[v]=w[k][v];
pre[v]=k;
node.push_back(v);
}
}
}
return ans; }
//求次小生成树
int second_MST(int ans){
int second=INF;
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(!use[i][j] && ans-f[i][j]+w[i][j]<second){
second=ans-f[i][j]+w[i][j];
}
}
}
return second;
}
int main() {
int t,a,b,c;
scanf("%d",&t);
for(int i=;i<=t;i++){
scanf("%d%d",&n,&m);
memset(w,INF,sizeof(w)); for(int i=;i<;i++){
son[i].clear();
}
for(int j=;j<=m;j++){
scanf("%d%d%d",&a,&b,&c);
w[a][b]=w[b][a]=c;
son[a].push_back(b);
son[b].push_back(a);
}
ans1=solve_MST();
ans2=second_MST(ans1);
if(ans1==ans2)
printf("Not Unique!\n");
else
printf("%d\n",ans1);
}
return ;
}

二:用kruskal算法

枚举删除最小生成树上的边,再求最小生成树,即总共求n-1次最小生成树,取其中最小值。

这道题如果用该方法,有一点要注意,不然的话会一直WA。

我做这道题的时候一直wrong answer的原因是因为, 可能求出的次小生成树正好等于最小生成树的总权值,但是它不连通,即边的个数小于n-1

可以试试这个测试数据:

1

6 7

1 3 1

1 2 2

2 3 3

3 4 0

4 5 4

4 6 5

5 6 6

结果是 12

就是说,如果次小生成树不连通,且最小生成树中被你删的边恰好是权值为0的情况, 这样权值总和仍相等,但不满足生成树的要求。

#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <string> using namespace std; int t,n,m,cost,x,y,w; //n个节点,m条边
int ansMST,secondMST;
int numOfEdge; struct Edge{
int u,v;
int cost; bool operator < (const Edge& tmp) const
{
return cost< tmp.cost;
} }edge[],MSTedge[]; struct UF{
int father[]; void unit(){
for(int i=;i<=n;i++){
father[i]=i;
}
} int find_root(int x){
if(father[x]!=x)
father[x]=find_root(father[x]);
return father[x];
} void Union(int fa,int fb){
father[fb]=fa;
}
}uf; //求最小生成树
int solveMST(){
int counts=;
int ans=;
//int index=0;
for(int i=;i<m;i++){
int u=edge[i].u;
int v=edge[i].v;
int fu=uf.find_root(u);
int fv=uf.find_root(v);
if(counts>=n-){
break;
} if(fu!=fv){
ans+=edge[i].cost;
uf.Union(fu,fv);
MSTedge[counts].u=u;
MSTedge[counts].v=v;
MSTedge[counts].cost=edge[i].cost;
counts++;
}
}
return ans;
}
/**
a、b表示最小生成树中删去的那条边
这里是删去(a,b)边后,求最小生成树
*/
int solve(int a,int b){
int counts=;
int ans=;
for(int i=;i<m;i++){
int u=edge[i].u;
int v=edge[i].v;
int fu=uf.find_root(u);
int fv=uf.find_root(v);
if((u==a && v==b)||(u==b && v==a))
continue;
if(counts>=n-){
break;
}
if(fu!=fv){
ans+=edge[i].cost;
counts++;
uf.Union(fu,fv);
}
}
numOfEdge=counts;
return ans;
} int main()
{
scanf("%d",&t); for(int i=;i<=t;i++){
scanf("%d%d",&n,&m);
for(int j=;j<m;j++){
scanf("%d%d%d",&x,&y,&w);
edge[j].u=x;
edge[j].v=y;
edge[j].cost=w;
}
sort(edge,edge+m); uf.unit();
ansMST=solveMST(); //最小生成树的总权值
secondMST=; //次小生成树的总权值
//枚举,取最小值
for(int j=;j<n-;j++){
int u=MSTedge[j].u;
int v=MSTedge[j].v;
uf.unit();
int total=solve(u,v);
//如果它的总权值小于目前的secondMST,并且边的个数也正好为n-1
if(total<secondMST && numOfEdge==n-){
secondMST=total;
}
} if(secondMST==ansMST)
printf("Not Unique!\n");
else
printf("%d\n",ansMST);
}
return ;
}

POJ 1679 The Unique MST(次小生成树)的更多相关文章

  1. POJ 1679 The Unique MST (次小生成树)

    题目链接:http://poj.org/problem?id=1679 有t组数据,给你n个点,m条边,求是否存在相同权值的最小生成树(次小生成树的权值大小等于最小生成树). 先求出最小生成树的大小, ...

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

    题目链接 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. De ...

  3. POJ 1679 The Unique MST (次小生成树kruskal算法)

    The Unique MST 时间限制: 10 Sec  内存限制: 128 MB提交: 25  解决: 10[提交][状态][讨论版] 题目描述 Given a connected undirect ...

  4. poj 1679 The Unique MST (次小生成树(sec_mst)【kruskal】)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 35999   Accepted: 13145 ...

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

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

  6. POJ 1679 The Unique MST 【最小生成树/次小生成树模板】

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

  7. POJ1679 The Unique MST —— 次小生成树

    题目链接:http://poj.org/problem?id=1679 The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total S ...

  8. poj 1679 The Unique MST

    题目连接 http://poj.org/problem?id=1679 The Unique MST Description Given a connected undirected graph, t ...

  9. poj 1679 The Unique MST(唯一的最小生成树)

    http://poj.org/problem?id=1679 The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submis ...

  10. poj 1679 The Unique MST (判定最小生成树是否唯一)

    题目链接:http://poj.org/problem?id=1679 The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total S ...

随机推荐

  1. mq消息队列

    rabbitmq学习9:使用spring-amqp发送消息及同步接收消息 通过对spring-amqp看重要类的认识,下面来通过spring-amqp的发送消息及同步接收消息是如何实现的.有兴趣的朋友 ...

  2. 分布式缓存Memcached

       分布式缓存服务器,既然用到数据缓存很明显就是想高效性的获取数据,大容量的存储数据.为了可以缓存大量的数据以及可以高效获取数据,那么分布式缓存数据库就要解决数据可以水平线性扩展,这样可以扩大数据容 ...

  3. hdu 2660 Accepted Necklace

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2660 Accepted Necklace Description I have N precious ...

  4. struts2传递参数值的3中方式

    在使用struts2的时候,当要传递的参数不多的时候,我们会选择使用属性来传参,而当要传递的参数很多的时候,或者多个action会有共用的参数时,我们会使用另外两种传参方式. 注意:使用Model D ...

  5. 联想Z470安装10.11懒人版成功!!特此分享!!

    折腾黑苹果也断断续续好几个月了,在远景也爬了好多贴,遇到问题基本上靠自己解决,自己组的台式机已基本完美,大学期间买的联想Z470现在是“食之无味,弃之可惜”,想想也来试试装个黑苹果玩玩,之前装过10. ...

  6. Swift :?和 !

    Swift语言使用var定义变量,但和别的语言不同,Swift里不会自动给变量赋初始值, 也就是说变量不会有默认值,所以要求使用变量之前必须要对其初始化 .如果在使用变量之前不进行初始化就会报错: v ...

  7. VS2012 常用web.config配置解析之自定义配置节点

    在web.config文件中拥有一个用户自定义配置节点configSections,这个节点可以方便用户在web.config中随意的添加配置节点,让程序更加灵活(主要用于第三方插件的配置使用) 自定 ...

  8. FPGA---ucf文件编写

    摘要:本文主要通过一个实例具体介绍ISE中通过编辑UCF文件来对FPGA设计进行约束,主要涉及到的约束包括时钟约束.群组约束.逻辑管脚约束以及物理属性约束. Xilinx FPGA设计约束的分类 Xi ...

  9. QWidget设置为模态问题

    设置QWidget的Qt::WindowModality属性为Qt::WindowModal和Qt::ApplicationModal,发现窗体仍然不会模态,网上查了一下,有人说改属性只对window ...

  10. 【转】MATLAB在一幅图上添加多个纵坐标轴

    来源:http://wenku.baidu.com/link?url=m_eEkzbjnT9ccgAnlPVDqHCVyrZOD2EplXxxIiQc69DI0lHAWzwpZXfdDy_7DPbwI ...