• 最小生成树


    何为最小生成树?

    最小生成树就是对于一个连通图,保留若干条边,使图依然联通,且边权和最小。

    因为(n)个点的连通图(以下自动默认为连通图,),最少要有(n-1)条边。所以对于一个图的最小生成树,也一定只有(n-1)条边。反证一下(此证明仅限于非负边权):如果这个图的最小生成树不止有(n-1)条边,因为只需保留(n-1)条边即可保持联通,所以我们一定可以找到一条边,将其删去,仍保持图联通。这样的话就与我们的定义不符了。当然,对于存在负边权的情况,显然是不能这么简单证明的,所以我们这里只讨论正边权。

    (Kruskal)

    由于最小生成树的上述特性,(Kruskal)算法便应运而生了。

    简单的叙述就是:先把(n)个点分布在(n)个集合中,将(m)条边从小到大排序,依次遍历。如果当前边所连接的两个点不在同一集合,则加上这条边,然后合并两个集合;如果在同一集合则忽略。直到选择了(n-1)条边后,最小生成树也就求出来了。这里比较显然,就不证明了。

    题目链接

    下面放代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cctype>
    #define ll long long
    #define gc getchar
    #define maxn 5005
    #define maxm 200005
    using namespace std;
    
    inline ll read(){
    	ll a=0;int f=0;char p=gc();
    	while(!isdigit(p)){f|=p=='-';p=gc();}
    	while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
    	return f?-a:a;
    }int n,m,sum,ans;
    
    struct ahaha{
    	int u,v,w;
    	inline bool friend operator<(const ahaha x,const ahaha y){
    		return x.w<y.w;
    	}
    }e[maxm];
    
    int f[maxn];
    int find(int x){
    	return f[x]==x?x:f[x]=find(f[x]);
    }
    void merge(int x,int y){
    	int fx=find(x),fy=find(y);
    	f[fx]=fy;
    }
    
    int main(){
    	n=read();m=read();
    	for(int i=1;i<=m;++i)
    		e[i]={read(),read(),read()};
    	for(int i=1;i<=n;++i)f[i]=i;
    	sort(e+1,e+m+1);
    	for(int i=1;i<=m;++i){
    		int u=e[i].u,v=e[i].v,w=e[i].w;
    		if(find(u)==find(v))continue;
    		merge(u,v);++sum,ans+=w;
    		if(sum==n-1)break;
    	}
    	if(sum<n-1)puts("orz");
    	else printf("%d
    ",ans);
    	return 0;
    }
    

    (Prim)

    除了(Kruskal)以外,还有一种算法叫做(Prim)算法。(Prim)算法简单来说就是:先把一个点放到集合(B)里,然后把剩下的点放到集合(A)里,每次把从集合(A)连向集合(B)的最短边拿出来,然后把最短边所连接的集合(A)中的点移动到集合(B)中,直到所有点都放到了集合(B)中,最小生成树也就求好了。

    由于我几乎没有用过这种算法,这里也就不放代码了。

    (Kruskal)在稀疏图中的复杂度更优秀,而(Prim)在稠密图中要更胜一筹,具体采用哪种方法,还要看大家的喜好还有题目要求。

    至于题目推荐,这种类型的题太多了,我就不推荐了

    如果这篇博客对你有些许帮助的话,不妨点推荐再走吧

  • 相关阅读:
    WPF 便签项目
    .NET下WPF学习之Socket通信
    DEV控件
    字符串位数补足
    VS2008设置断点不命中
    错误描述: 242000021
    关闭Win10自带的 Windows Defender
    启用与关闭 Ad Hoc Distributed Queries
    Date工具类
    数据字段脱敏
  • 原文地址:https://www.cnblogs.com/hanruyun/p/11362197.html
Copyright © 2020-2023  润新知