堆(优先队列)优化 Prim
优化主要有两个部分:
(1):寻找距离生成树最小的顶点-------->利用优先对列实现O(1)查找。
(2):更新顶点到生成树的最小距离------>利用邻接表避免对不相通路径的遍历。
#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)>!!