再次做并查的题目。本题用kruskar方法做。我开始没有按秩(即所包含的层数)来union_set结果WA,后来改了之后就AC了。为什么呢??不管,以后记得要加上按秩来合并吧。
这题有个技巧就是只用输入上半个矩阵就OK了,因为是对称的。看别人用prim方法做也挺简单的,接下来来学习一下prim算法吧。
kruskar:
#include <iostream> #include <fstream> #include <algorithm> using namespace std; #define MAX 101 int father[MAX]; int rank[MAX]; int n,ans; struct node{ int fm; int to; int len; }N[MAX*MAX/2]; bool cmp(node a,node b) { return a.len<b.len; } void make_set(int x) { for(int i=0; i<x; i++) { father[i]=i; rank[i]=0; } } int find_set(int x) { if(x!=father[x]) father[x]=find_set(father[x]); //路径压缩 return father[x]; } void union_set(int i) { int x=N[i].fm; int y=N[i].to; int px=find_set(x); int py=find_set(y); if(px==py) return; if(rank[px]>rank[py]) { father[py]=px; } else { if(rank[px]==rank[py]) { rank[py]++; } father[px]=py; } ans+=N[i].len; } int main() { int i,j,k,abandon; freopen("acm.txt","r",stdin); while( scanf("%d",&n)!=EOF) { k=0; make_set(MAX); for(i=0; i<n; i++) { for(j=0; j<n; j++) { if(i<j) //上三角 { N[k].fm=i; N[k].to=j; scanf("%d",&N[k++].len); } else { scanf("%d",&abandon); } } } sort(N,N+k,cmp); ans=0; //pathsnum=n; for(i=0; i<k; i++) { union_set(i); //if(paths==pathsnum-1) // break; } printf("%d\n",ans); } return 0; }
本文探讨了使用Kruskal算法解决最小生成树问题,并通过按秩合并优化并查集,避免了路径过长的问题。文章分享了一种技巧,仅需输入矩阵的上半部分即可,简化了输入过程。同时,提到了Prim算法的简单性,为后续学习提供了方向。
493

被折叠的 条评论
为什么被折叠?



