概念
生成树:一个连通图含有全部
n
n
n个顶点,但只有足以构成一棵树的
n
−
1
n-1
n−1条边。一颗n个顶点的生成树有且仅有
n
−
1
n-1
n−1条边,如果生成树当中再添加一条边,必定成环。
最小生成树(
M
S
T
MST
MST):在联通网中的所有生成树中,所有边代价最小的生成树,成为最小生成树。
prim
原理:从起点顶点开始,选择当前可用的最小权值和,把对应的顶点加入到当前建立的生成树当中。
令初始状态为
u
u
u,所有顶点结合为
V
V
V,当前剩余没用的顶点集合为
v
v
v。
1.初始化:
u
=
s
,
v
=
V
−
u
u={s},v=V-u
u=s,v=V−u
2.找出一条连接集合
u
u
u和
v
v
v的最小代价的边
(
u
0
,
v
0
)
(u0,v0)
(u0,v0),把他连起来,并将
v
0
v0
v0加入到
u
u
u中,修改相关的值。
3.重复操作2,直到所有顶点都被连上。
代码:
#define MAXN 1000
#define INF 1<<30
int closest[MAXN],lowcost[MAXN],m;//m为节点的个数
int G[MAXN][MAXN];//邻接矩阵
int prim()
{
for(int i=0;i<m;i++)
{
lowcost[i]=INF;
}
for(int i=0;i<m;i++)
{
closest[i]=0;
}
closest[0]=-1;//加入第一个点,-1表示该点在集合U中,否则在集合V中
int num=0,ans=0,e=0;//e为最新加入集合的点
while(num<m-1)//加入m-1条边
{
int micost=INF,miedge=-1;
for(int i=0;i<m;i++)
if(closest[i]!=-1)
{
int temp=G[e][i];
if(temp<lowcost[i])
{
lowcost[i]=temp;
closest[i]=e;
}
if(lowcost[i]<micost)
micost=lowcost[miedge=i];
}
ans+=micost;
closest[e=miedge]=-1;
num++;
}
return ans;
}
kruskal算法
原理:从边出发,初始状态下最小生成树选取0条边,在计算过程中,每次添加一条满足条件的边进入最小生成树中,知道选完为止。
步骤:
1.把边从小到大排序
2.并查集判断祖先
3.加边,重复2操作
代码:
int kruskal() {
sort(c + 1,c + k + 1);
for(int i = 1;i <= n;i ++)
fa[i] = i;
for(int i = 1;i <= k;i ++) {
int x = Find_Set(c[i].u);
int y = Find_Set(c[i].v);
if(x == y)
continue;
fa[x] = y;
ans += c[i].w;
}
}