题意:求图的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; }