克鲁斯卡尔算法是怎样判断是不是构成了回路
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了克鲁斯卡尔算法是怎样判断是不是构成了回路相关的知识,希望对你有一定的参考价值。
无向连通图具体怎样判定构成了回路(最好能用C#代码分析下)万分感谢
参考技术A 使用遍历方法,同时存储他们的父亲节点,如果父亲节点不一样,就说明有回路本回答被提问者采纳 参考技术B 以下给出并查集实现的克鲁斯卡尔算法,求解生成网络的最小费用,并输出生成网络里的路径。#include<iostream>
#include<algorithm>
using namespace std;
int p[1001],rank[1001];
int cho[1001];
struct edge
int u,v,w;//u表示起始点编号,v表示终点编号,w表示该路径费用
e[15001];
int n,m;//n表示点的个数,m表示路径数
void Init()
int i;
for(i=1;i<=n;i++)
p[i]=i;
rank[i]=0;
bool cmp(edge a,edge b)
return a.w<b.w;
int Find(int t)
if(p[t]!=t)
p[t]=Find(p[t]);
return p[t];
int Union(int a,int b)
int x,y;
x=Find(a);
y=Find(b);
if(rank[x]>rank[y])
p[y]=x;
else
p[x]=y;
if(rank[x]==rank[y])
rank[y]++;
return 0;
int main()
scanf("%d%d",&n,&m);
int i,j;
for(i=0;i<m;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
Init();
sort(e,e+m,cmp);
int cnt=0,ans=0;
for(i=0;i<m;i++)
if(Find(e[i].u)!=Find(e[i].v))
cnt++;
ans+=e[i].w;
Union(e[i].u,e[i].v);
cho[++cho[0]]=i;
if(cnt==n-1)
break;
printf("%d\n",ans);
for(j=1;j<=cho[0];j++)
printf("%d %d\n",e[cho[j]].u,e[cho[j]].v);
return 0;
克鲁斯卡尔算法一定要画图吗
参考技术A 1)克鲁斯卡尔算法概念克鲁斯卡尔算法是求连通网的最小生成树的另一种方法。与普里姆算法不同,它的时间复杂度为O(eloge)(e为网中的边数),所以,适合于求边稀疏的网的最小生成树
(2)实现思路
对于任意一个连通网的最小生成树来说,在要求总的权值最小的情况下,最直接的想法就是将连通网中的所有边按照权值大小进行升序排序,从小到大依次选择。
克鲁斯卡尔算法的具体思路是:将所有边按照权值的大小进行升序排序,然后从小到大一一判断,条件为:如果这个边不会与之前选择的所有边组成回路,就可以作为最小生成树的一部分;反之,舍去。直到具有 n 个顶点的连通网筛选出来 n-1 条边为止。筛选出来的边和所有的顶点构成此连通网的最小生成树; 参考技术B 1) 克鲁斯卡尔 (Kruskal) 算法,是用来求加权连通图的最小生成树的算法 。
2) 基本思想 :按照权值从小到大的顺序选择 n-1 条边,并保证这 n-1 条边不构成回路
3) 具体做法 :首先构造一个只含 n 个顶点的森林,然后依权值从小到大从连通网中选择边加入到森林中,并使森林中不产生回路,直至森林变成一棵树为止
以上是关于克鲁斯卡尔算法是怎样判断是不是构成了回路的主要内容,如果未能解决你的问题,请参考以下文章