ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

最小生成树

2022-09-03 19:34:10  阅读:166  来源: 互联网

标签:连通 val int 最小 生成 算法 link


专门开个博客一是因为没地放了,二是以后次小生成树什么的就一块扔这了。

点数n,边数m的图的最小生成树大概有两个算法:

  1. Kruskal算法(\(O(m\log m)\))

思路非常简单粗暴,把所有边扔出来按照边权排个序,然后拿并查集维护点的连通关系,最后选出n-1条边。

int kruskal(int x){
    sort(edge+1,edge+t+1,cmp);
    chushihua();
    int sum=0,cnt=0;
    for(int i=1;i<=t;i++){
        int x=edge[i].u,y=edge[i].v;
        if(find(x)!=find(y)){
            father[y]=x;
            sum+=edge[i].w;
            cnt++;
        }
        if(cnt==n-1)break;
    }
    return sum;
}
  1. Prim算法(\(O(n^2)\))

这个是每次维护最小生成树的一部分边,类似Dijkstra。(这玩意真没啥意思)

同样的,用堆优化可以到\(O(mlogn)\),但是你还不如直接写kruskal。

int prim(int x){
    int sum=0;memset(a,0x3f,sizeof(a));
    for(int i=1;i<=n;i++)dis[i]=a[x][i];
    v[x]=true;
    for(int i=2;i<=n;i++){
        int min=2147483647,k;
        for(int j=1;j<=n;j++){
            if(!v[j]&&dis[j]<min)min=dis[j];k=j;
        }
        sum+=dis[k];v[k]=true;//找一条与当前生成树相连的最小的边记录答案 
        for(int j=1;j<=n;j++){
            if(!v[j]&&dis[j]>a[k][j])dis[j]=a[k][j];//更新边 
        }
    }
    return sum;
}
  1. Boruvka算法(听完林老师讲课看看原题题解看到的)(\(O(m\log n)\))

首先定义最小边是一个连通块向其他连通块连的边中边权最小的一个。这个算法的大体思路是初始将每个点视作一个连通块,通过最小边合并连通块(共\(\log n\)次合并),最终形成最小生成树。这个东西一般不会让你写,但是不太好建边的时候可能有奇效(比如这道题)。

int link[5010],val[5010];
void boruvka(int n){
	int ans=0,num=0;
	bool jud=true;
	while(jud){
		jud=false;
		memset(link,0,sizeof(link));
		memset(val,0x3f,sizeof(val));
		for(int i=1;i<=n;i++){
			int x=find(i);
			for(int j=head[i];j;j=edge[j].next){
				int y=find(edge[j].v);
				if(val[x]>edge[j].w&&x!=y){//找到连通块i的最小边 
					val[x]=edge[j].w;//如果该边两端点不都属于连通块且边权更小则更新 
					link[x]=y;
				}
			}
		}
		for(int i=1;i<=n;i++){
			int x=find(i);
			if(find(i)==i){
				if(link[x]&&x!=find(link[x])){
					merge(x,link[x]);ans+=val[x];//连接最小边两端的两个连通块 
					jud=true;num++;//计入合并次数(洛谷的无解要特判一下) 
				}
			}
		}
	}
	if(num==n-1)printf("%d",ans);
	else printf("orz");
}

标签:连通,val,int,最小,生成,算法,link
来源: https://www.cnblogs.com/gtm1514/p/16653352.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有