zoukankan      html  css  js  c++  java
  • Kruskal算法

    基本思想:

    假设连通网G=(V,E),令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),图中每个顶点自成一个连通分量。

    在E中选择 代价最小 的边,若该边依附的顶点分别在T中不同的连通分量上,则将此边加入到T中;否则,舍去此边而选择下一条代价最小的边。依此类推,直至T中所有顶点构成一个连通分量为止

    时间复杂度为O(eloge)(e为图中的边数),所以,适合于求 稀疏图 的最小生成树。

    #include <bits/stdc++.h>
    #define MAXN 200005
    using namespace std;
    int node,edge,ans=0,k=0;		
    int fat[MAXN],siz[MAXN];					
    struct EDGE
    {
    	int from,to,cost;
    }	e[MAXN];
    bool cmp(EDGE a,EDGE b)	{return a.cost<b.cost;}
    int Find(int x){ return (fat[x]==x)? x : fat[x]=Find(fat[x]); }	//查 路径压缩
    //要么是父节点,要么就递归找到子节点,并且记录下来,实现压缩。
    //注意:路径压缩后会破坏原有的父子关系。
    void unionn(int x,int y)//并 
    {
    	x=Find(x); y=Find(y);
    	if(siz[x]>siz[y])	swap(x,y);//扁平树
    	fat[x]=y;	siz[y]+=siz[x]; 
    }
    bool kruskal()
    {
    	sort(e+1,e+edge+1,cmp);
    	//贪心,排序 
    	for(int i=1;i<=edge;++i)
    	{
    		if(k==node-1) break;
    		if(Find(e[i].from) != Find(e[i].to))
    		{
    			unionn(e[i].from,e[i].to); 
    			ans+=e[i].cost;	++k; 
    		}
    	}
    	return (k==node-1);
    }
    int main()
    {
    	scanf("%d%d",&node,&edge);
    	//node点数,edge边数 
    	for(int i=1;i<=edge;++i)	scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].cost);
    	//邻接矩阵 
    	for(int i=1;i<=node;++i)	{fat[i]=i;siz[i]=1;}
    	//初始化 siz[i]=1 这样后面的累加有意义
    	if(kruskal())	printf("%d",ans);
    	return 0;
    }
    

    做题心得

    1.往往题目中会出现“最少”,“最多”等含有“最”的字样。

    2.可能会是最大生成树。即:在一开始贪心排序的时候改动。

    3.图论的问题往往都涉及构图的策略(P1194

    4.涉及坐标注意精度 (P2872

    5.在结束判定的时候作手脚 if(k==node-1) break;P4047 P1991

  • 相关阅读:
    java实现第四届蓝桥杯组素数
    java实现第四届蓝桥杯组素数
    java实现第五届蓝桥杯斐波那契
    java实现第五届蓝桥杯斐波那契
    java实现第五届蓝桥杯斐波那契
    java实现第五届蓝桥杯斐波那契
    Spring boot随时获取ApplicationContex
    JAVA数据库连接池的革命 -- 从BoneCP到HikariCP(转)
    spring boot自动配置之jdbc(转)
    spring boot 的 ApplicationContext 及 getbean
  • 原文地址:https://www.cnblogs.com/cyl-oi-miracle/p/13401477.html
Copyright © 2011-2022 走看看