并查集及其应用

题目后续补吧,主要解决问题;

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e5+5;
 4 int fa[N]; 
 5 int find_fa(int x){
 6     return fa[x]=(x==fa[x])?x:find_fa(fa[x]);//路径压缩
 7 }
 8 void merge(int x,int y)
 9 {
10     int fx=find_fa(x),fy=find_fa(y);//这里是随机合并,也可以用按秩合并;
11     fa[fy]=fx;
12 } 
13 int main()
14 {
15     //1.处理无向图的连通分量
16     //2.处理最小生成树,边从小到大选n-1条边,如果一条边的两个点不在同一集合就加边 
17     //证明,最小的n-1条边能型形成n个点的数,如果存在一条小边成环,则去说明去到较大的留下更小的会从u->v更优; 
18     return 0;
19 }

 洛谷模板题

P3366 【模板】最小生成树

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef vector<int> vec;
 4 const int N=5e3+5;
 5 int fa[N];
 6 int n,m;
 7 struct cmp
 8 {
 9     bool operator()(vec &a,vec &b)
10     {
11         return a[2]>b[2];    
12     }    
13 };
14 int fd(int x)
15 {
16     return fa[x]=(x==fa[x])?x:fd(fa[x]);
17 }
18 void merge(int x,int y)
19 {
20     int fx=fd(x),fy=fd(y);
21     fa[fy]=fx;
22 }
23 
24 int main()
25 {
26     scanf("%d%d",&n,&m);
27     priority_queue<vec,vector<vec>,cmp>q;
28     for(int i=1;i<=n;i++)fa[i]=i;
29     for(int i=1;i<=m;i++)
30     {
31         int u,v,w;
32         scanf("%d%d%d",&u,&v,&w);
33         vec tmp{u,v,w};
34         q.push(tmp);
35     }
36     int cnt=0,ans=0;
37     while(q.size())
38     {
39         if(cnt==n-1)break;
40         auto p=q.top();
41         q.pop();
42         int u=p[0],v=p[1],w=p[2];
43         if(fd(u)!=fd(v))
44         {
45             merge(u,v);
46             ans+=w;
47             cnt++;
48         }
49     }
50     int root=fd(1),ok=true;
51     for(int i=1;i<=n;i++)if(fd(i)!=root)ok=false;
52     if(!ok)printf("%s\n","orz");
53     else printf("%d\n",ans);
54     return 0;
55  } 

 

posted @ 2021-12-18 11:54  matt-11  阅读(28)  评论(0)    收藏  举报