2021-02-25 Minimum spanning tree template-prime algorithm

Summary:

Minimum spanning tree template-prime algorithmMinimum
spanning tree template-krusal algorithm


Brief description of the topic:

Luogu P3366 minimum spanning tree template


Analysis of Algorithms:

The prime algorithm and Dijkstra's algorithm have similarities, and the essence of both is greedy and dynamic programming. The idea of ​​prime algorithm can be summarized as "step by step shorting", each time the shortest edge of the fixed point currently traversed is selected.
According to the above analysis, since the shortest edge is selected every time, we can learn from the implementation process of Dijkstra's algorithm and use the implicit data structure-heap for optimization. See the code for details


Code and detailed comments:

#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <queue>
#define INF 10000000
#pragma warning(disable:4996)
using namespace std;


/*链表前向星的准备工作*/
struct edge {
    
    
	int to;
	int next;
	int w;
};

struct Node {
    
    
	int pos;  //点的编号
	int w;   //加入该点后,小增加的权值
	Node(int _pos=0, int _w=0) :pos(_pos), w(_w) {
    
    }

	bool operator()(Node& n1, Node& n2) {
    
    
		return n1.w > n2.w; //准备建立一个小根堆
	}
	friend bool operator<(Node& n1, Node& n2)
	{
    
    
		return n1.w > n2.w; //准备建立一个小根堆
	}
};


class Solution {
    
    
public:
	int cnt=0;
	vector<int> head;
	vector<edge> e;
	int n, m;
	vector<int> dis;//这里的dis数组保存的并不是从起点到某点的距离。
	//dis[i]表示的意思是加入第i个点后,最小生成树中增加的权值大小
	vector<bool> visit;
	priority_queue<Node, vector<Node>, Node> q;
	int s = 1;
	int count = 0; //假设起点s已经达到过
	int ans = 0;
	//链表前向星加边
	inline void add_edge(int u, int v, int w) {
    
    
		cnt++;
		e[cnt].to = v;
		e[cnt].w = w;
		e[cnt].next = head[u];
		head[u] = cnt;
	}

	void prime() {
    
    
		cin >> n >> m;
		e.resize(2*m + 1);
		head.resize(n + 1, 0);
		dis.resize(n + 1, INF);
		visit.resize(n + 1, false);
		for (int i = 1; i <= m; ++i)
		{
    
    
			int u, v, w;
			cin >> u >> v >> w;
			add_edge(u, v, w);
			add_edge(v, u, w);
		}
		dis[1] = 0;
		q.push(Node(1, 0));
		//下面的过程同迪杰斯特拉算法
		while (!q.empty() && count < n)
		{
    
    
			int u = q.top().pos;
			int d = q.top().w;
			q.pop();
			if (visit[u]) continue;  
			visit[u] = true;
			ans += d;
			++count;
			for (int i = head[u]; i != 0; i = e[i].next)
			{
    
    
				int y = e[i].to;
				if (dis[y] > e[i].w)
				{
    
    
					dis[y] = e[i].w;
					q.push(Node(y, dis[y]));
				}
			}
		}
		if (count == n)
			cout << ans << endl;
		else
			cout << "orz" << endl;
	}
};

int main() {
    
    

	//freopen("in.txt", "r", stdin);
	Solution s;
	s.prime();
	return 0;

}

Guess you like

Origin blog.csdn.net/sddxszl/article/details/114055590