原博客出处: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. EtherCAT(扒自百度百科)

    EtherCAT(以太网控制自动化技术)是一个开放架构,以以太网为基础的现场总线系统,其名称的CAT为控制自动化技术(Control Automation Technology)字首的缩写.Ether ...

  2. 为什么使用 npm Scripts 构建项目

    http://www.css88.com/archives/7025#more-7025 https://github.com/damonbauer/npm-build-boilerplate 这个我 ...

  3. python 笔记数据类型

    python基础: 采用缩进方式     4个空格的缩进 大小写敏感 数据类型和变量 数据类型 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值,但是,计算机能处理的 ...

  4. python全栈开发笔记-----------概要

    Python开发 开发: 开发语言: 高级语言:python.Java.php  .C#   .Go .ruby . C++ .... ===>字节码 低级语言:C.汇编            ...

  5. TModalResult 和 MessageBox 返回值

    //其实是对应的{ TModalResult values } const mrNone = ; mrOk = idOk; mrCancel = idCancel; mrAbort = idAbort ...

  6. Saiku通过iframe嵌入web页面(六)

    Saiku通过iframe嵌入系统页面 前提: Saiku已安装好,并且配置了数据源,熟练了saiku的基本使用. 一.将整个Saiku嵌入页面 在web项目中,新建index.jsp页面,内容如下: ...

  7. 2.2 BIOS中断

    BIOS中断 BIOS中断简介 计算机刚启动时,进入实模式下,此时操作系统跟硬件(例如键盘鼠标显卡等)交互通过BIOS进行的.通过调用中BIOS中断的方式来访问硬件设备. BIOS中断就不详细介绍了. ...

  8. Traumland--梦乡--IPA--德语

    德国电影<<英俊少年>>的插曲.

  9. String 和StringBuffer的简单实用案例

    3.现在有个字符串是按照如下格式保存的:“张三:90|李四:80|王五:100” 显示后的数据如下所示,按不同的人员显示: 姓名:张三,成绩是:90: 姓名:李四,成绩是:90: 姓名:王五,成绩是: ...

  10. Git客户端的安装与配置入门

    GitLab与Git客户端的安装与配置入门,每次配置完一段时间,就忘记配置过程了,为了自己和同学们以后有所参照,特记录了本次下载和配置,其实Git就是一个版本控制系统,类似于SVN,CVS等 下载:W ...