最小生成树
Kruskal算法
①设含有0条边的生成子图为A
②在边集合中,找取权值最低的边,且它不与子图A中的任意条边构成闭环,则将其加入到子图A中
③重复②,直到边数满足N-1
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> using namespace std; struct edge { int a, b; int w; }; int n, T, m, sum; edge se[20000];//储存边 int set[2000];//辅助集合 bool cmp(edge e1, edge e2) { return e1.w > e2.w; } int find(int x) { return x == set[x] ? x : set[x] = find(set[x]); } void MSt() { for (int i = 1; i <= n; i++) set[i] = i; int num = 0; int k = 0; while (k < n - 1) { int a = find(set[se[num].a]); int b = find(set[se[num].b]); if (a != b) { sum += se[num].w; set[b] = a; k++; } num++; } } int main() { scanf("%d", &T); while (T--) { sum = 0; scanf("%d %d", &n, &m); //读入m条边 for (int i = 0; i < m; i++) { int a = 1, b = 1, w = 1; scanf("%d %d %d", &a, &b, &w); se[i].a = a; se[i].b = b; se[i].w = w; } //根据权值把边排序 sort(se, se + m, cmp); MST(); cout << sum << endl; } return 0; }
下面的代码,如果是同一个集合中的顶点,那么set[ i ] = set[ j ],这样的话就要遍历,比较麻烦,需要修改多处。
while(k < N - 1){ if(set[se[num].a] != set[se[num].b]){ cout<<se[num].a+1<<" "<<se[num].b+1<<endl; int t = set[se[num].b]; //将所有与se[num].b一个集合的元素 全放到se[num].a所在集合中 for(int i=0;i<N;i++){ if(set[i] == t) set[i] = set[se[num].a]; } k++; } num++; } }
Prime算法