C ++はクラスカルアルゴリズムを実装します

1.基本的な考え方

n個のノードとm個のエッジがあると仮定すると、重みが最小のエッジが、選択されていないエッジセットEから毎回選択されます。最小のエッジの端が、選択されたエッジの端とループを形成しない場合、エッジが最小スパニングツリーに追加されます。n-1個のエッジが選択されるか、エッジが選択されなくなるまで、この手順を繰り返します。例は次のとおりです。図
ここに画像の説明を挿入
には9つのエッジが
あり最初は最小のエッジが選択され、重みは1で、ノードv1とv3にラベルが付けられています。
ここに画像の説明を挿入

2回目:重みが2の最小のエッジを選択すると、ノードv1とv4にラベルが付けられます。
ここに画像の説明を挿入

3回目:最小のエッジが選択され、重みは3で、ノードv1とv5にラベルが付けられます。
ここに画像の説明を挿入

4回目:最小のエッジが選択され、重みは3で、ノードv2とv4にラベルが付けられます。
ここに画像の説明を挿入

選択したエッジはn-1に到達し、終了します。

2,注意点

ここでの主な注意点は、選択の過程で2つのポイントがループを構成しているかどうかを判断する方法です。他の著者の判断​​方法を読んだ後、考え方はほぼ同じです(最初はいつも理解していませんでしたが、私は最終的にそれを理解したか、それは私がそれを行うのが面倒だったためでした。この例はもう一度やり直します)、これは2つのポイントの親ノード(ここでは親ノードが正確ではなく、大まかな意味)であるかどうかを判断することです)は同じです。同じ場合はループを形成し、エッジは望ましくありません。異なる場合はエッジが望ましいです。

3.コードの実装

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

struct edge
{
    
    
	int u, v;
	int weight;
};
vector<int> father; //记录每个节点的父亲
vector<int> result; //存储最后获得的各条边

bool compare(edge a, edge b)
{
    
    
	return a.weight < b.weight;
}

int findfather(int a)
{
    
    
	while (a != father[a])
	{
    
    
		a = father[a];
	}
	return a;
}
void kruskal(int n, vector<edge> Edge)
{
    
    
	father.resize(n);
	sort(Edge.begin(), Edge.end(), compare);
	for (int i = 0; i < n; ++i)
	{
    
    
		father[i] = i;
	}
	for (int i = 0; i < Edge.size() && result.size() < n-1; ++i)
	{
    
    
		int u = Edge[i].u;
		int v = Edge[i].v;
		if (findfather(u) != findfather(v)) //判断父节点是否相同
		{
    
    
			result.push_back(Edge[i].weight);
			father[findfather(u)] = father[findfather(v)]; //将两点并入一个集合中
		}
	}
	if (result.size() != n - 1)
	{
    
    
		cout <<  result.size()  << "该图不连通" << endl;
		return;
	}
	else
	{
    
    
		cout << "最小生成树的各边如下:" << endl;
		for (int i = 0; i < result.size(); ++i)
		{
    
    
			cout << result[i] << endl;
		}
	}
}

int main()
{
    
    
	int n, m;
	cout << "输入结点数:";
	cin >> n;
	cout << "输入边数:";
	cin >> m;
	vector<edge> Edge(m);
	cout << "输入各条边的信息:" << endl;
	for (int i = 0; i < m; ++i)
	{
    
    
		cin >> Edge[i].u >> Edge[i].v >> Edge[i].weight;
	}
	kruskal(n,Edge);
	return 0;
}

入力および出力情報:ここに画像の説明を挿入
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_46027243/article/details/108903948