Prim算法采用与Dijkstra、Bellamn-Ford算法一样的“蓝白点”思想;白点代表已经进入最小生成树的点,蓝点代表未进入最小生成树的点。
算法分析 & 思想讲解:
Prim算法每次都将一个蓝点 U 变成白点,并且此蓝点 U 与白点相连的最小边权还是当前所有蓝点中最小的。这样就相当于向生成树中添加了n-1次最小的边,最后得到的一定是最小生成树。
我们通过对下图最小生成树的求解模拟来理解上面的思想。蓝点和虚线代表未进入最小生成树的点、边;白点和实线代表已进入最小生成树的点、边。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> using namespace std; int s[1500][1500],n,distan[1500]; bool visit[1500]; const int maxn=0x7fffffff; int main() { cin>>n; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) cin>>s[i][j]; memset(distan,0x7f,sizeof(distan)); distan[1]=0; int kk=0; for(int i=1;i<=n;++i) { kk=0; for(int j=1;j<=n;++j) if(!visit[j]&&distan[j]<distan[kk]) kk=j; visit[kk]=true; for(int j=1;j<=n;++j) { if(!visit[j]&&s[kk][j]<distan[j]) distan[j]=s[kk][j]; } } int ans=0; for(int i=1;i<=n;++i) ans+=distan[i]; cout<<ans; return 0; }
#include<cstdio> #include<iostream> #include<cstdlib> #include<algorithm> using namespace std; struct node { int a,b,dis; }s[1500]; int sum=1,n,fa[1500]; bool cmp(node a,node b) { return a.dis<b.dis; } int find(int son) { if(fa[son]!=son) fa[son]=find(fa[son]); return fa[son]; } int main() { int ans=0; cin>>n; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) { s[sum].a=i; s[sum].b=j; cin>>s[sum++].dis; } sort(s+1,s+sum,cmp); int k=0; for(int i=1;i<=n;++i) { int r1=find(s[i].a); int r2=find(s[i].b); if(find(s[i].a)!=find(s[i].b)) { fa[r2]=r1; ans+=s[i].dis; k++; } if(k==n-1) break; } cout<<ans; return 0; }