【次小生成树】【Kruskal】【prim】【转】
原博客出处: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】【转】的更多相关文章
- UVA10462Is There A Second Way Left? —— 次小生成树 kruskal算法
题目链接:https://vjudge.net/problem/UVA-10462 Nasa, being the most talented programmer of his time, can’ ...
- UVA 10462 Is There A Second Way Left? (次小生成树+kruskal)
题目大意: Nasa应邻居们的要求,决定用一个网络把大家链接在一起.给出v个点,e条可行路线,每条路线分别是x连接到y需要花费w. 1:如果不存在最小生成树,输出“No way”. 2:如果不存在次小 ...
- HDU 2988.Dark roads-最小生成树(Kruskal)
最小生成树: 中文名 最小生成树 外文名 Minimum Spanning Tree,MST 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的 ...
- POJ 1679 The Unique MST (次小生成树kruskal算法)
The Unique MST 时间限制: 10 Sec 内存限制: 128 MB提交: 25 解决: 10[提交][状态][讨论版] 题目描述 Given a connected undirect ...
- Conscription-最小生成树-Kruskal
Windy has a country, and he wants to build an army to protect his country. He has picked up N girls ...
- 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 ...
- Constructing Roads-最小生成树(kruskal)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1102 题目描述: #include<cstdio> #include<cstring ...
- 修路方案 Kruskal 之 次小生成树
次小生成树 : Kruskal 是先求出来 最小生成树 , 并且记录下来所用到的的边 , 然后再求每次都 去掉最小生成树中的一个边 , 这样求最小生成树 , 然后看能不能得到 和原来最小生成树一样的 ...
- UVA 10462 Is There A Second Way Left?(次小生成树&Prim&Kruskal)题解
思路: Prim: 这道题目中有重边 Prim可以先加一个sec数组来保存重边的次小边,这样不会影响到最小生成树,在算次小生成树时要同时判断次小边(不需判断是否在MST中) Kruskal: Krus ...
随机推荐
- vue2.x 父组件监听子组件事件并传回信息
利用vm.$emit 1.在父组件中引用子组件 <child @from-child-msg="listenChildMsg"></child > 2.子组 ...
- Resharper插件如何启用原VS的智能提示
第一步:vs2015选择工具—>选项—>文本编辑器—>C#—>常规—>语句结束,勾选自动列出成员,如下图: 第二步: 关闭Resharper智能提示,并设置为Visual ...
- 通过滑动条控制Cube旋转
private float speed = 10; private float speedValue; private GameObject slider; private GameObject cu ...
- java②
1.java文件: 以.java结尾的文件,我们称之为 源文件!以.class结尾的文件,我们称之为 字节码文件! javac 编译器 把 .java文件编译成.class文件 .class文件我们看 ...
- day06 小数据池,再谈编码
今日所学 一. 小数据池 二. is 和==的区别 三. 编码的问题 一.小数据池的作用 用来缓存数据 可以作用的数据类型: 整数(int), 字符串(str), 布尔值(bool). 什么是块 ...
- python中字典常用的方法
#定义一个空字典: a={ } 定义一个字典: d={'age':18} #增加一个元素: d['age']=20 d[k]=v d.setdefault('age',18) d.setde ...
- 读书笔记 C# Type类型与泛型有关的某些属性浅析
IsGenericType 如果类型为泛型,则返回 true. GetGenericArguments 返回 Type 对象数组,这些对象表示为构造类型提供的类型变量,或泛型类型定义的类型参数.如果是 ...
- Suffix树,后缀树
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- springboot学习章节代码-spring基础
1.DI package com.zhen.highlights_spring4.ch1.di; import org.springframework.stereotype.Service; /** ...
- quartz自定义线程数
1.加载包 2.添加quartz.propertes 3.编写自己的任务类 4.添加自动任务配置 5.通过 quartzProperties 配置连接池 1.加载包 <dependency> ...