这是一篇讲kruskal的题解
看题解很多大佬只讲kruskal思路,我就来写写整个代码的思路
思路:
核心思想不是堆,不是查找,而是sort
我们可以这么想:因为是最小的路径,所以我们可以排序一下,把节点根据长度从小到达大排序一下
所以,我们先开个结构体来储存节点和边长(开结构体是为了方便sort排序)
1 2 3
| struct node{ int p1,p2,val; };
|
因为是根据节点排序,所以我们可以开个cmp函数
1 2 3
| int cmp(node &A,node &B){ return A.val<B.val; }
|
那么问题来了:怎么不走重复的点呢?
这需要我们的并查集。这里我不多讲并查集了,不会的大佬可以参考这个
那么我们就可以写一个find函数,用来合并两个已经走过的点
1 2 3 4
| int find(int k){ if(f[k]==k)return k; return f[k]=find(f[k]); }
|
然后再sort排序,整个代码就成型了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include<cstdio> #include<algorithm> using namespace std; int f[5001]; int find(int k){ if(f[k]==k)return k; return f[k]=find(f[k]); } struct node{ int p1,p2,val; }; int cmp(node &A,node &B){ return A.val<B.val; } node qwq[200001]; int ans,cnt; int n,m; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d%d",&qwq[i].p1,&qwq[i].p2,&qwq[i].val); } for(int i=1;i<=5000;i++)f[i]=i; sort(qwq+1,qwq+m+1,cmp); for(int i=1;i<=m;i++){ if(find(qwq[i].p1)!=find(qwq[i].p2)){ cnt++; f[find(qwq[i].p1)]=find(qwq[i].p2); ans+=qwq[i].val; } if(cnt==n-1){ printf("%d",ans); return 0; } } printf("orz\n"); return 0; }
|