• 最小生成树两大算法总结+模板


    最小生成树两大算法总结+模板

    Prime算法

    此算法可以称为“加点法”,每次迭代选择代价最小的边对应的点,加入到最小生成树中。算法从某一个顶点s开始,逐渐长大覆盖整个连通网的所有顶点。

    //poj 2485
    const int inf=0x3f3f3f3f;
    const int maxn=1e3;
    struct Node{
    	int x, y;
    }node[maxn];
    int mp[maxn][maxn];
    int vis[maxn];
    int dis[maxn];//这里的dis存储的是其他各个点,到最小生成树中任意一点的最小值。
    int line[maxn];
    int n, m;
    void init()
    {
    	for(int i=1; i<=n; i++)
    	{
    		dis[i]=mp[1][i];//开始的时候任选1号顶点加入到生成树中。
    		line[i]=1; //默认没有加入到生成树的点到生成树中任意一点的最小距离的点是1;
    		vis[i]=0; //默认没有点加入到生成树中。
    	}
    }
    bool prim()
    {
    	vis[1]=1;
    	for(int i=1; i<n; i++)
    	{
    		int tmp=inf, k;
    		for(int j=1; j<=n; j++)
    		{
    			if(!vis[j] && dis[j]<tmp)
    			{
    				tmp=dis[j];
    				k=j;
    			}
    		}
    		if(tmp==inf) return false;//生成最小树失败,该图不是连通的。
    		vis[k]=1;
    		if(mp[k][line[k]]!=0)
    		{
    			printf("%d %d
    ", k, line[k]);
    		}
    		for(int j=1; j<=n; j++) //以新加入生成树的点作为中间点,看看能优化
    		{
    			if(!vis[j] && dis[j] > mp[j][k])
    			{
    				line[j]=k;
    				dis[j]=mp[j][k];
    			}
    		}
    	}
        return true;
    }
    

    Kruskal算法

    此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。 需要并查集算法。

    1. 把图中的所有边按代价从小到大排序;
    2. 把图中的n个顶点看成独立的n棵树组成的森林;
    3. 按权值从小到大选择边,所选的边连接的两个顶点应属于两颗不同的树,则成为最小生成树的一条边,并将这两颗树合并作为一颗树。
    4. 重复(3),直到所有顶点都在一颗树内或者有n-1条边为止。
    // HDU 1863题解
    const int maxn=107;
    struct note
    {
    	int a, b, c;
    	bool friend operator < (note a, note b)
    	{
    		return a.c < b.c;
    	}
    }mp[maxn*maxn];
    struct tree
    {
    	int pre, rak;
    }tre[maxn];
    
    int find(int x)
    {
    	if(tre[x].pre==-1) return x;
    	else return tre[x].pre=find(tre[x].pre);
    }
    
    void unit(int x, int y)
    {
    	if(tre[x].rak > tre[y].rak)
    	{
    		tre[y].pre=x;
    	}
    	else {
    		tre[x].pre=y;
    		if(tre[x].rak == tre[y].rak)
    			tre[y].rak++;
    	}
    }
    int n, m;
    void init()
    {
    	for(int i=1; i<=m; i++)
    	{
    		tre[i].pre=-1;
    		tre[i].rak=0;
    	}
    }
    int main()
    {
    	while(scanf("%d%d", &n, &m) && n!=0)
    	{
    		init();
    		for(int i=0; i<n; i++)
    		{
    			scanf("%d%d%d", &mp[i].a, &mp[i].b, &mp[i].c);
    		}
    		sort(mp, mp+n);
    		int x, y, ans=0, cnt=0;
    		for(int i=0; i<n; i++)
    		{
    			x=find(mp[i].a);
    			y=find(mp[i].b);
    			if(x!=y)
    			{
    				unit(x, y);
    				ans+=mp[i].c;
    				cnt++;
    			}
    			if(cnt==m-1) break;
    		}
    		if(cnt==m-1)
    			printf("%d
    ", ans);
    		else printf("?
    ");
    	}
    	return 0;
    }
    

    END

    欢迎评论交流!
  • 相关阅读:
    Python列表去重
    hash表长度优化证明
    DDD初学指南
    继承和实现的明显区别
    微信商户支付
    centos7+mono4+jexus5.6.2安装过程中的遇到的问题
    SVN:重命名文件之后不允许提交
    SpringMVC 自定义全局日期转换器
    解决Cannot change version of project facet Dynamic web module to 2.5
    Maven项目热部署到Tomcat容器下
  • 原文地址:https://www.cnblogs.com/alking1001/p/11281226.html
Copyright © 2020-2023  润新知