3366 【模板】最小生成树(Kruskal)
题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz
输入输出格式
输入格式:
第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)
接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi
输出格式:
输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz
代码:
1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 using namespace std; 5 struct edge{ 6 int s, e, w; 7 edge(int ss, int ee, int ww):s(ss), e(ee), w(ww){} 8 bool operator<(const edge&e1){ 9 return w<e1.w; 10 } 11 }; 12 vector<edge>edges; 13 vector<int>par; 14 int getpar(int x){ 15 if(par[x]!=x){ 16 par[x] = getpar(par[x]); 17 } 18 return par[x]; 19 } 20 void merge(int x, int y){ 21 if(getpar(x)==getpar(y)) return; 22 par[getpar(x)] = getpar(y); 23 } 24 int main(){ 25 int n, m; 26 int i; 27 cin>>n>>m; 28 par.resize(n+1); 29 for(i = 1; i <= n; i++) 30 par[i] = i; 31 for(i = 1; i <= m; i++){ 32 int s, e, w; 33 cin>>s>>e>>w; 34 edges.push_back(edge(s,e,w)); 35 } 36 sort(edges.begin(),edges.end()); 37 int done = 0, way = 0; 38 for(i = 0; i <edges.size(); i++){ 39 if(getpar(edges[i].s)!=getpar(edges[i].e)){ 40 merge(edges[i].s, edges[i].e); 41 done++; 42 way += edges[i].w; 43 } 44 if(done == n-1) break; 45 } 46 cout<<way<<endl; 47 return 0; 48 }
备注:
Frankly speaking,我觉得Kruskal比Prim要好理解+好写。只是把边排序,再加一个并查集就可以实现。在某种程度上更好理解。
再去看看图论的内容。