@@ -562,4 +562,145 @@ if __name__ == "__main__":
562562### Dart
563563
564564### C
565+ 并查集方法一
566+ ``` c
567+ #include < stdio.h>
568+ #include < stdlib.h>
569+
570+ // 定义边结构体,包含两个顶点vex1和vex2以及它们之间的权重val
571+ struct Edge
572+ {
573+ int vex1, vex2, val;
574+ };
575+
576+ // 冒泡排序函数,用于按边的权重val不减序排序边数组
577+ void bubblesort (struct Edge * a, int numsize)
578+ {
579+ for (int i = 0; i < numsize - 1; ++i)
580+ {
581+
582+ for (int j = 0; j < numsize - i - 1; ++j)
583+ {
584+ if (a[j].val > a[j + 1].val)
585+ {
586+ struct Edge temp = a[j];
587+ a[j] = a[j + 1];
588+ a[j + 1] = temp;
589+ }
590+ }
591+ }
592+ }
593+
594+ int main()
595+ {
596+ int v, e;
597+ int v1, v2, val;
598+ int ret = 0;
599+
600+ scanf("%d%d", &v, &e);
601+ struct Edge *edg = (struct Edge *)malloc(sizeof(struct Edge) * e);
602+ int *conne_gra = (int *)malloc(sizeof(int) * (v + 1));
603+
604+ // 初始化连通图数组,每个顶点初始时只与自己相连通
605+ for (int i = 0; i <= v; ++i)
606+ {
607+ conne_gra[i] = i;
608+ }
609+
610+ // 读取所有边的信息并存储到edg(存储所有边的)数组中
611+ for (int i = 0; i < e; ++i)
612+ {
613+ scanf("%d%d%d", &v1, &v2, &val);
614+ edg[i].vex1 = v1;
615+ edg[i].vex2 = v2;
616+ edg[i].val = val;
617+ }
618+ bubblesort(edg, e); // 调用冒泡排序函数对边进行排序
619+
620+ // 遍历所有边,执行Kruskal算法来找到最小生成树
621+ for (int i = 0; i < e; ++i)
622+ {
623+ if (conne_gra[edg[i].vex1] != conne_gra[edg[i].vex2])
624+ { // 如果当前边的两个顶点不在同一个连通分量中
625+ int tmp1 = conne_gra[edg[i].vex1], tmp2 = conne_gra[edg[i].vex2];
626+ for (int k = 1; k <= v; ++k)
627+ { // 将所有属于tmp2的顶点合并到tmp1的连通分量中
628+ if (conne_gra[k] == tmp2)
629+ conne_gra[k] = tmp1;
630+ }
631+ ret += edg[i].val; // 将当前边的权重加到最小生成树的权重中
632+ }
633+ }
634+ printf("%d", ret);
635+ return 0;
636+ }
637+
638+ ```
639+ 并查集方法二
640+ ```c
641+ #include <stdio.h>
642+ #include <stdlib.h>
565643
644+ // 定义边结构体,包含两个顶点vex1和vex2以及它们之间的权重val (略,同上)
645+ // 冒泡排序函数,用于按边的权重val不减序排序边数组(略,同上)
646+
647+ // 并查集的查找操作
648+ int find(int m, int *father)
649+ { // 如果当前节点是其自身的父节点,则直接返回该节点
650+ // 否则递归查找其父节点的根,并将当前节点直接连接到根节点
651+ return (m == father[m]) ? m : (father[m] = find(father[m], father)); // 路径压缩
652+ }
653+
654+ // 并查集的加入集合
655+ void Union(int m, int n, int *father)
656+ {
657+ int x = find(m, father);
658+ int y = find(n, father);
659+ if (x == y)
660+ return; // 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回
661+ father[y] = x;
662+ }
663+
664+ int main()
665+ {
666+ int v, e;
667+ int v1, v2, val;
668+ int ret = 0;
669+
670+ scanf("%d%d", &v, &e);
671+ struct Edge *edg = (struct Edge *)malloc(sizeof(struct Edge) * e);
672+ int *conne_gra = (int *)malloc(sizeof(int) * (v + 1));
673+
674+ // 初始化连通图数组,每个顶点初始时只与自己相连通
675+ for (int i = 0; i <= v; ++i)
676+ {
677+ conne_gra[i] = i;
678+ }
679+ // 读取所有边的信息并存储到edg(存储所有边的)数组中
680+ for (int i = 0; i < e; ++i)
681+ {
682+ scanf("%d%d%d", &v1, &v2, &val);
683+ edg[i].vex1 = v1;
684+ edg[i].vex2 = v2;
685+ edg[i].val = val;
686+ }
687+
688+ bubblesort(edg, e); // 调用冒泡排序函数对边进行排序
689+
690+ // Kruskal算法的实现,通过边数组构建最小生成树
691+ int j = 0, count = 0;
692+ while (v > 1)
693+ {
694+ if (find(edg[j].vex1, conne_gra) != find(edg[j].vex2, conne_gra))
695+ {
696+ ret += edg[j].val; // 将当前边的权重加到最小生成树的权重中
697+ Union(edg[j].vex1, edg[j].vex2, conne_gra);
698+ v--;
699+ }
700+ j++;
701+ }
702+ printf("%d", ret);
703+ return 0;
704+ }
705+
706+ ```
0 commit comments