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要好理解+好写。只是把边排序,再加一个并查集就可以实现。在某种程度上更好理解。

再去看看图论的内容。

posted @ 2016-11-02 23:35  timeaftertime  阅读(264)  评论(0编辑  收藏  举报