题意:求图的MST。
思路:PRIM算法,其中找最小边用priority_queue实现。注意不加堆的Prim 算法适用于密集图(O(V^2)),加堆的适用于稀疏图O(ElogV)。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
using namespace std;
#define N 105
struct edge{
int x,y,next,w;
bool operator<(const struct edge &b)const{
return w>b.w;
}
}e[N*N*2];
int first[N],top,n,used[N];
priority_queue<struct edge> h;
void add(int x,int y,int w){
e[top].x = x;
e[top].w = w;
e[top].y = y;
e[top].next = first[x];
first[x] = top++;
}
int prim(){
int i,j,res=0;
used[1] = 1;//点1作为第一个加入的点
for(i = first[1];i!=-1;i=e[i].next)
h.push(e[i]);
for(i = 1;i<n;){
struct edge now = h.top();
h.pop();
if(used[now.y])//如果这条边的两个端点已经加入了,那么这条边不能用
continue;
used[now.y] = 1;
res += now.w;
for(j = first[now.y];j!=-1;j=e[j].next)//这个地方也可以像不加堆写法那样弄一个dis数组,对未加入MST的点仅当其邻接的最小边更新时才加入
if(!used[e[j].y])
h.push(e[j]);
i++;
}
return res;
}
int main(){
while(scanf("%d",&n)!=EOF){
int i,j,w;
top = 0;
while(!h.empty())
h.pop();
memset(first, -1, sizeof(first));
memset(used, 0, sizeof(used));
for(i = 1;i<=n;i++)
for(j = 1;j<=n;j++){
scanf("%d",&w);
if(i!=j)
add(i,j,w);
}
printf("%d\n",prim());
}
return 0;
}