原博客出处: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. Win10系列:VC++数据绑定

    数据绑定是一种将后台数据绑定到前台控件的机制,通常用于动态地将对象或集合中所保存的数据显示到前台界面中.本节通过一个具体的示例来说明在Windows应用商店应用中如何通过数据绑定将保存在集合中的数据显 ...

  2. Linux内核空间内存申请函数kmalloc、kzalloc、vmalloc

    我们都知道在用户空间动态申请内存用的函数是 malloc(),这个函数在各种操作系统上的使用是一致的,对应的用户空间内存释放函数是 free(). 注意:动态申请的内存使用完后必须要释放,否则会造成内 ...

  3. java倒计时简易实现,只按单线程,以秒为单位

    public class Countdown { private int lin; public Countdown(int lin)throws InterruptedException{ this ...

  4. hibernate创建构架

    创建hibernate架构: 注意:需要将所需的架包导进去: 二:Java工程的具体结构: 具体代码如下:hibernate.cfg.xml <!DOCTYPE hibernate-config ...

  5. day041 前端HTML CSS基本选择器(未整理完毕)

    标签: <b> :加粗 <i> :倾斜体 <u>: 下划线 <s>: 删除线 <p>:段落 <h1> - <h6> ...

  6. iOS 10跳转到其他app

    - (BOOL)jumpsToThirdAPP:(NSString *)urlStr{ if ([urlStr hasPrefix:@"mqq"] || [urlStr hasPr ...

  7. dns资源记录类型

    资源记录的定义格式: 语法:name [TTL] IN RR_TYPE value SOA: name:当前区域的名字,例如"magedu.com.",或者"2.168. ...

  8. webpack对多个模块依赖进行打包

    [ webpack3.0.0刚刚出来  所以文章是跟着低版本 教程 操作熟悉  结果好多对不上喔] 七:webpack对多个模块依赖进行打包 通过一刚开始我们了解到 webpack支持commonJS ...

  9. Flask源码阅读-第二篇(flask\__init__.py)

    源码: # -*- coding: utf-8 -*-""" flask ~~~~~ A microframework based on Werkzeug. It's e ...

  10. ios读取plist文件:

    @property (nonatomic,strong) NSArray *imageData;//定义一个数组 //懒加载数据 -(NSArray *)imageDate { if(_imageDa ...