最小生成树就是在一个联通网络中找到一棵包括所有点且权值最大(小)的树。
其实现有一般有两种方法,prim()和kruskal();
一.kruskal()
按权值递增顺序删去图中的边,若不形成回路则将此边加入最小生成树。是否形成回路就可以用并查集判断。
a 首先预处理,把边的信息存储在由结构体构成的数组中。
struct node
{
int u,v; //边连的两个点
int w; //边的权值
}q[maxn];
b 对q[]进行排序
#include <algorithm>int cmp(node a,node b){
return a.l<b.l;
}
sort(q,q+k,cmp);
c 并查集处理是否有环
for(i=0;i<n;i++) father[i]=i;int find(int m)
{
int x,y,j;
x=m;
while(father[x]!=x) x=father[x];
y=m;
while(father[y]!=y)
{
j=father[y];
father[y]=x;
y=j;
}
return x;
}
for(i=0;i<k;i++)
{
u=find(q[i].u);
v=find(q[i].v);
if(u!=v) father[v]=u;
}hdu 3367 最小生成树的变形,可以有一个环;
1598 枚举
3926 题目很活,主要是优化,到时候还是需要再做一遍;
二.prim()
三个步骤,1.确定一个点,2.更新与其相连点的值,3.找到一个未标记的,最小路径的点。#include <stdio.h>
#include <string.h>
#define MaxInt 0x3f3f3f3f
#define N 110 //创建map二维数组储存图表,dis数组记录点与树之间的最小路径,visit数组标记某点是否已访问
int map[N][N],dis[N],visit[N];
int n;
int prim()
{
int i,j,pos,min,result=0;
memset(visit,0,sizeof(visit)); //从某点开始,分别标记和记录该点
visit[1]=1; pos=1;
for(i=1;i<=n;i++) //第一次给dis数组赋值
if(i!=pos) dis[i]=map[pos][i];
for(i=1;i<n;i++) //再运行n-1次
{
min=MaxInt; //找出最小路径并记录位置
for(j=1;j<=n;j++)
if(!visit[j]&&min>dis[j])
{
min=dis[j];
pos=j;
}
result+=min; //最小路径累加
visit[pos]=1; //标记该点
for(j=1;j<=n;j++) //更新权值
if(!visit[j]&&dis[j]>map[pos][j])
dis[j]=map[pos][j];
}
return result;
}
int main()
{
int i,v,j,ans;
while(scanf("%d",&n)!=EOF)
{
memset(map,MaxInt,sizeof(map)); //所有权值初始化为最大
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
scanf("%d",&v);
map[i][j]=map[i][j]=v;
}
ans=prim();
printf("%d\n",ans);
}
return 0;
}hdu 2489 最小生成树 prim()+double精度比较
if(fabs(v-ans)>0.00000001 && ans>v)
4081 次最小生成树
1801

被折叠的 条评论
为什么被折叠?



