最小生成树

最小生成树就是在一个联通网络中找到一棵包括所有点且权值最大(小)的树。

其实现有一般有两种方法,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 次最小生成树




评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值