图论之最小生成树


/*
* 图论算法 最小生成树
Kruskal 时间复杂度 O(ElogE)
Prim 时间复杂度 O(V2)
*/ #include<stdio.h> #include<vector> #include<queue> #include<algorithm> using namespace std; const int MAXN = 100; int father[MAXN];//father[i]表示i节点的根节点 int height[MAXN]; struct Node { int from; int to; int cost; bool operator< (const Node&e) const//按权值升序排序 { return cost < e.cost; } }; Node edge[MAXN*MAXN];

/*并查集操作*/
void Init(int n)//初始化 { for(int i=0;i<=n;i++) { father[i] = i;//初始化,每个节点都是孤立的 height[i] = 0;//初始化,树的高度为0 } } int Find(int x) { if(father[x] == x) return x;//节点x的根为自己,返回根编号 else { father[x] = Find(father[x]);//递归找x的根节点,赋给father[x] return father[x]; } } void Union(int x, int y) { x = Find(x); y = Find(y); if(x != y) { if(height[x] < height[y]) { father[x] = y; } else if(height[x] > height[y]) { father[y] = x; } else { father[y] = x; height[x]++; } } return ; } int Kruskal(int n, int m)// { Init(n); sort(edge, edge + m);//按边的权值升序排序,重载< int sum=0; for(int i=0;i<m;i++) { Node cur = edge[i]; if(Find(cur.from) != Find(cur.to))//遍历所有边,当前边的两个顶点在同一个集合,不作处理;不在同一个集合里,合并集合 { Union(cur.from, cur.to); sum+=cur.cost; } } return sum; } int main () { int n,m; scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { scanf("%d%d%d", &edge[i].from, &edge[i].to, &edge[i].cost); } int ans = Kruskal(n,m); printf("%d\n",ans); return 0; } /** 3 3 1 2 1 1 3 2 2 3 4 输出3 4 6 1 2 1 1 3 4 1 4 1 2 3 3 2 4 2 3 4 5 输出5 */

 

posted @ 2021-03-07 22:36  永恒&  阅读(67)  评论(0编辑  收藏  举报