原博客出处:https://blog.csdn.net/yasola/article/details/74276255

通常次小生成树是使用Prim算法进行实现的,因为可以在Prim算法松弛的同时求得最小生成树上任意两点之间的最长边。但是利用Kruskal算法却没办法在松弛的同时求得。

所以我们就要在Kruskal求完最短路后,对于每个顶点bfs一次,得到树上任意两点的最长边。之后求可以像之前一样枚举不在树上的边,代替找最小值了。

两种方法的时间杂度是一样的,但Kruskal的实现代码回长非常多,不过Kruskal的实现可以处理Prim难以处理的重边。

一、Kruskal模板

 #include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
#define fi first
#define se second
#define mem(a,b) memset((a),(b),sizeof(a)) const int MAXV=+;
const int MAXE=+; struct Edge
{
int from,to,cost;
Edge(int f=,int t=,int c=):from(f),to(t),cost(c){}
bool operator<(const Edge &other)const
{
return cost<other.cost;
}
}edge[MAXE]; int V,E,par[MAXV],high[MAXV],the_max[MAXV][MAXV];
bool used[MAXE];//边是否使用的标记
bool vis[MAXV];
vector<pair<int,int> > G[MAXV];//最小生成树 void init()//初始化
{
for(int i=;i<=E;++i)
used[i]=false;
for(int i=;i<=V;++i)
{
par[i]=i;
high[i]=;
G[i].clear();
}
} int findfather(int x)
{
return par[x]=par[x]==x?x:findfather(par[x]);
} bool unite(int a,int b)
{
int fa=findfather(a),fb=findfather(b);
if(fa==fb)
return false;
if(high[fa]>high[fb])
par[fb]=fa;
else
{
par[fa]=fb;
if(high[fa]==high[fb])
++high[fb];
}
return true;
} void bfs(int s)
{
mem(vis,);
vis[s]=true;
the_max[s][s]=;
queue<int> que;
que.push(s);
while(!que.empty())
{
int u=que.front(); que.pop();
for(int i=;i<G[u].size();++i)
{
int v=G[u][i].fi;
if(!vis[v])
{
vis[v]=true;
the_max[s][v]=max(the_max[s][u],G[u][i].se);
the_max[v][s]=the_max[s][v];
que.push(v);
}
}
}
} int main()
{
int T_T;
scanf("%d",&T_T);
for(int cas=;cas<=T_T;++cas)
{
printf("Case #%d : ",cas);
scanf("%d%d",&V,&E);
init();
for(int i=;i<E;++i)
scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].cost);
sort(edge,edge+E);
int res=;
for(int i=;i<E;++i)
if(unite(edge[i].from,edge[i].to))
{
res+=edge[i].cost;
used[i]=true;
G[edge[i].from].push_back(make_pair(edge[i].to,edge[i].cost));
G[edge[i].to].push_back(make_pair(edge[i].from,edge[i].cost));
}
bool ok=true;
for(int i=;i<=V;++i)
if(findfather(i)!=findfather())
{
ok=false;
break;
}
if(!ok)//不联通
{
puts("No way");
continue;
}
if(E==V-)//生成树唯一
{
puts("No second way");
continue;
}
for(int i=;i<=V;++i)
bfs(i);
int ans=INF;
for(int i=;i<E;++i)
if(!used[i])
ans=min(ans,res-the_max[edge[i].from][edge[i].to]+edge[i].cost);
printf("%d\n",ans);
} return ;
}

二、prim模板

 #include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=+;
bool link[maxn][maxn],vis[maxn];
int w[maxn][maxn],lowc[maxn],pre[maxn],Max[maxn][maxn];
int n,m;
int prim()
{
int i,j,p,k;
int minc,res=;
memset(vis,false,sizeof(vis));
memset(pre,,sizeof(pre));
memset(Max,,sizeof(Max));
vis[]=true,pre[]=;
for(i=; i<=n; i++) //初始化
{
lowc[i]=w[][i];
pre[i]=;
}
for(i=; i<=n; i++) //prim
{
minc=inf,p=-;
for(j=; j<=n; j++)
{
if(!vis[j]&&lowc[j]<minc)
{
minc=lowc[j];
p=j;
}
}
vis[p]=true;
res+=minc;//最小生成树加权值
Max[pre[p]][p]=minc;//直接相连的两点最大权值就是边权值本身
link[pre[p]][p]=true;//将这两条边标记为最小生成树的边
link[p][pre[p]]=true;
for(k=; k<=n; k++)
Max[k][p]=max(Max[pre[p]][p],Max[k][p]);//非直接相连的最大权值需要不断更新
for(j=; j<=n; j++)
if(!vis[j]&&lowc[j]>w[p][j])
{
lowc[j]=w[p][j];
pre[j]=p;
} }
return res;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int s,e,t,ans,ans1; while(~scanf("%d%d",&n,&m))
{
int i,j;
bool ok=true;//是否唯一最小生成树的标志
for(i=; i<=n; i++)
for(j=; j<=n; j++)
w[i][j]=inf;
memset(link,false,sizeof(link));
for(i=; i<=m; i++)
{
scanf("%d%d%d",&s,&e,&t);
w[s][e]=t;
w[e][s]=t;
}
ans=prim();//最小生成树的权值
for(i=; i<=n; i++)
{
for(j=i+; j<=n; j++)
{
if(w[i][j]!=inf&&!link[i][j])
{
ans1=ans+w[i][j]-Max[i][j];//ans1次小生成树的权值
}
if(ans1==ans)
{
ok=;
break;
}
}
if(!ok)
break;
}
printf("ans=%d ans1=%d\n",ans,ans1);
}
return ;
}

【次小生成树】【Kruskal】【prim】【转】的更多相关文章

  1. UVA10462Is There A Second Way Left? —— 次小生成树 kruskal算法

    题目链接:https://vjudge.net/problem/UVA-10462 Nasa, being the most talented programmer of his time, can’ ...

  2. UVA 10462 Is There A Second Way Left? (次小生成树+kruskal)

    题目大意: Nasa应邻居们的要求,决定用一个网络把大家链接在一起.给出v个点,e条可行路线,每条路线分别是x连接到y需要花费w. 1:如果不存在最小生成树,输出“No way”. 2:如果不存在次小 ...

  3. HDU 2988.Dark roads-最小生成树(Kruskal)

    最小生成树: 中文名 最小生成树 外文名 Minimum Spanning Tree,MST 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的 ...

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

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

  5. Conscription-最小生成树-Kruskal

    Windy has a country, and he wants to build an army to protect his country. He has picked up N girls ...

  6. HDU 4081—— Qin Shi Huang's National Road System——————【次小生成树、prim】

    Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/3 ...

  7. Constructing Roads-最小生成树(kruskal)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1102 题目描述: #include<cstdio> #include<cstring ...

  8. 修路方案 Kruskal 之 次小生成树

    次小生成树 : Kruskal 是先求出来  最小生成树 , 并且记录下来所用到的的边 , 然后再求每次都 去掉最小生成树中的一个边 , 这样求最小生成树 , 然后看能不能得到 和原来最小生成树一样的 ...

  9. UVA 10462 Is There A Second Way Left?(次小生成树&Prim&Kruskal)题解

    思路: Prim: 这道题目中有重边 Prim可以先加一个sec数组来保存重边的次小边,这样不会影响到最小生成树,在算次小生成树时要同时判断次小边(不需判断是否在MST中) Kruskal: Krus ...

随机推荐

  1. jquery 元素选择器

    id选择器 JQuery 能使用CSS选择器来操作网页中的标签元素.如果想要通过一个id号去查找另一个元素就可以使用下面格式的选择 $('#my_id') 其中my_id表示根据id选择器获取页面中的 ...

  2. 浅谈Linux系统运维工程师必备技能

    一.什么是运维工程师 相信读者们必定听说过Linux,也听说过运维工程师.那么运维工程师是个什么概念呢? 百度百科上的官方解释如下: 运维工程师(Operations)在国内又称为运维开发工程师(De ...

  3. Unity3D中的射线与碰撞检测代码

    两种不同写法的射线检测 1.获取鼠标点击的物体 if (Input.GetMouseButtonDown(0)) { Ray ray = MainCamera.ScreenPointToRay(Inp ...

  4. zTree入门实例(一眼就看会)

    zTree 是一个依靠 jQuery 实现的多功能 “树插件”. 下载地址:https://gitee.com/zTree/zTree_v3 待会将上面划的三个文件复制到Java的Web工程下即可 先 ...

  5. ES6-循环

    forEach 方法来遍历数组,不能使用break语句中断循环,也不能使用return语句返回到外层函数 myArray.forEach(function (value) { console.log( ...

  6. Python自学笔记-装饰器1(廖雪峰的网站)

    由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25') ... >> ...

  7. table添加行

    需求是要实现表格的动态增加与删除,并且保留标题行和首行,找了半天jq插件,没找到合适的,所以自己写了个demo <!DOCTYPE html> <html> <head& ...

  8. idea自动生成serialVersionUID(转)

    原文链接:http://blog.sina.com.cn/s/blog_54b09dc90101d9bu.html Setting->Plugins 找到一个叫  GenerateSerialV ...

  9. 卷积神经网络-Dropout

    dropout 是神经网络用来防止过拟合的一种方法,很简单,但是很实用. 基本思想是以一定概率放弃被激活的神经元,使得模型更健壮,相当于放弃一些特征,这使得模型不过分依赖于某些特征,即使这些特征是真实 ...

  10. installshield 功能传送错误

                                       出现这种问题,网上有几种解决方法: 1.原因:卸载不干净或者installshield本身安装的问题 解决方法:①卸载老程序.②删 ...