复习图的一些算法,使用c++实现
最小生成树(Kruscal)
思路:每次加入最短的边,要求加入后不成环(即两个顶点不连通)。
整个算法分成两部分:一是并查集,判断点的连通性,二是排序之后的选择以及结点连通性的修改。
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| #include <iostream> #include <algorithm> #include <vector> using namespace std;
vector<int> fatherList;
struct link{ int start,end,weight; link(){}; link(int s,int e,int w){ start = s; end = e; weight = w; } };
bool compare(link l1, link l2){ return l1.weight<l2.weight; }
int father(int x){ if(fatherList[x]==x) return x; return father(fatherList[x]); }
void combine(int x, int y){ fatherList[father(x)] = father(y); }
int main(){ int num; while(cin>>num){ if(num==0) break; fatherList.clear(); for(int i=0;i<=num;i++) fatherList.push_back(i); int n = num*(num-1)/2; vector<link> list; while(n-->0){ int s,e,w; cin>>s>>e>>w; link tmp(s,e,w); list.push_back(tmp); } sort(list.begin(),list.end(),compare); int cnt = 0, sum=0, idx=0; while(cnt++<num-1){ while(father(list[idx].start)==father(list[idx].end)) idx++; sum+=list[idx].weight; combine(list[idx].start,list[idx].end); idx++; } cout<<sum<<endl; } return 0; }
|