堆(优先队列)优化 Prim

堆(优先队列)优化 Prim

优化主要有两个部分:

(1):寻找距离生成树最小的顶点-------->利用优先对列实现O(1)查找。

(2):更新顶点到生成树的最小距离------>利用邻接表避免对不相通路径的遍历。

[POJ 1251]为例:

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
struct Edge//边表
{ 
	int v, w, next;
}edge[4100];
struct Pir {
	int dis, w; 
	bool operator < (const Pir b)const//重载<
	{
		return w > b.w;
	}
	Pir(int dis, int w) :dis(dis), w(w){}
};//dis 代表顶点  w 代表权值 这里是相当于普通prim的Min[]更新最小值的表
int dis[30];//记录顶点到树的最小距离
int tot;//给边表计数
int top[30];//记录与某顶点相连的edge的顶点链的最顶端的位置
bool vis[30];//记录顶点是否在树上
char s[3];//用于读取字符
priority_queue<Pir>q;//用优先队列优化可O1的寻找到最近的顶点
void Add(int u,int v,int w) {
	edge[tot].v = v;
	edge[tot].w = w;
	edge[tot].next = top[u];
	top[u] = tot++;
}
int main()
{
	int n;
	while (cin >> n && n)
	{
		tot = 1;
		fill(top, top + n + 1, 0);
		fill(vis, vis + n + 1, true);
		fill(dis, dis + n + 1, 0x3f3f3f3f);
		for (int i = 1; i < n; i++)
		{
			int k, temp, from; char ch;
			scanf("%s%d", &s, &k);
			temp = s[0] - 'A' + 1;
			for (int j = 0; j < k; j++)
			{
				int cost;
				scanf("%s%d", &s, &cost);
				Add(temp, s[0] - 'A' + 1, cost);
				Add(s[0] - 'A' + 1,temp , cost);
			}
		}
		Pir pir(1, 0);
		dis[1] = 0;
		q.push(pir);
		int MST = 0;
		while (!q.empty())
		{
			pir = q.top();
			q.pop();
			if (!vis[pir.dis])continue;
			vis[pir.dis] = false;
			MST += dis[pir.dis];
			//优化后的最小距离更新
			for (int i = top[pir.dis];i!=0; i=edge[i].next)
			{
				if (vis[edge[i].v]&&dis[edge[i].v] > edge[i].w)
				{
					dis[edge[i].v] = edge[i].w;
					Pir t(edge[i].v, edge[i].w);
					q.push(t);
				}
			}
		}
		cout << MST << endl;
	}
}
####如有不妥,还请批评指正 <(0_0)>!!
posted @ 2021-03-22 19:53  你看码!!!  阅读(434)  评论(0)    收藏  举报