ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SDUTOJ 2021级ACM班&2022年寒假集训《数据结构》专题11--最小生成树、并查集

2022-05-06 20:33:23  阅读:143  来源: 互联网

标签:11 SDUTOJ -- 查集 int init edge using include


A - 小雷的冰茶几

题目链接 https://acm.sdut.edu.cn/onlinejudge3/contests/3989/problems/A

并查集。一共需要搬动的次数,即,一共有几个集合。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int t,n,k,x,y;
 4 int p[100010];
 5 
 6 void Init(int n)
 7 {
 8     for(int o=1; o<=n; o++)
 9         p[o]=o;
10 }
11 
12 int Getp(int o)
13 {
14    return p[o]==o?o:(p[o]=Getp(p[o]));
15 }
16 
17 void Union(int x,int y)
18 {
19     int x_root=Getp(x);
20     int y_root=Getp(y);
21     if(x_root!=y_root)
22         p[y_root]=x_root;
23     return;
24 }
25 
26 int main()
27 {
28     cin>>t;
29     for(int i=1; i<=t; i++)
30     {
31         int cnt=0;
32         cin>>n>>k;
33         Init(n);
34         for(int j=1; j<=k; j++)
35         {
36             cin>>x>>y;
37             Union(x,y);
38         }
39         for(int k=1; k<=n; k++)
40         {
41             if(p[k]==k)
42                 cnt++;
43         }
44         printf("Case %d: %d\n",i,cnt);
45     }
46     return 0;
47 }

 

B - 电影节

题目链接 https://acm.sdut.edu.cn/onlinejudge3/contests/3989/problems/B

并查集模板

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,a,b,c,d;
 4 int p[100010];
 5 
 6 void init(int n)
 7 {
 8     for(int o=1; o<=n; o++)
 9         p[o]=o;
10 }
11 
12 int getp(int o)
13 {
14     return p[o]==o?o:(p[o]=getp(p[o]));
15 }
16 
17 void Union(int x,int y)
18 {
19     int x_root=getp(x);
20     int y_root=getp(y);
21     if(x_root!=y_root)
22         p[y_root]=x_root;
23     return;
24 }
25 
26 int main()
27 {
28     while(cin>>n>>m)
29     {
30         init(n);
31         for(int i=1; i<=m; i++)
32         {
33             cin>>a>>b;
34             Union(a,b);
35         }
36         cin>>c>>d;
37         if(getp(c)==getp(d)) cout<<"same"<<endl;
38         else cout<<"not sure"<<endl;
39     }
40     return 0;
41 }

 

C - 小鑫的城堡

题目链接 https://acm.sdut.edu.cn/onlinejudge3/contests/3989/problems/C

看到图以为是最小生成树或者最短路径,但是样例只有两列,寻思着或许是最短路计数这样的?结果又是一道并查集...

(喂,七道题,已经三道并查集了!)

把输入的每行的两个点(房间)放入并查集,如果两个点的根节点相同则构成回路,不符合小鑫的想法。

输入要求中的 m 为边数,因此点的数目应该为 m+1。

 1 #include<bits/stdc++.h>
 2 #define maxm 100010
 3 using namespace std;
 4 int m,x,y;
 5 int p[maxm];
 6 int vis[maxm];
 7 
 8 void init()
 9 {
10     for(int o=1; o<=maxm; o++)
11         p[o]=o;
12 }
13 
14 int getp(int o)
15 {
16     return p[o]==o?o:(getp(p[o]));
17 }
18 
19 int main()
20 {
21     while(cin>>m)
22     {
23         init();
24         memset(vis,0,sizeof(vis));
25         int flag=0;
26         int sum=0;
27         for(int i=1; i<=m; i++)
28         {
29             cin>>x>>y;
30             vis[x]=1;
31             vis[y]=1;
32             int x_root=getp(x);
33             int y_root=getp(y);
34 
35             if(x_root!=y_root) p[y_root]=x_root;
36             else flag=1;
37         }
38         for(int j=1; j<=maxm; j++) if(vis[j]==1) sum++;
39 
40         if(flag==0 && sum==m+1) cout<<"Yes"<<endl;
41         else cout<<"No"<<endl;
42     }
43     return 0;
44 }

 

D - 数据结构实验:连通分量个数

题目链接 https://acm.sdut.edu.cn/onlinejudge3/contests/3989/problems/D

本人表示很。。无雨。。专题11共7个题4个并查集了。。

而且下面这题跟A那个不能说是一模一样吧,也就是输出不同。。。。

我:&*%¥@*#。。。。。。

 1 #include<bits/stdc++.h>
 2 #define maxn 1010
 3 #define maxm 10010
 4 using namespace std;
 5 int t,n,m,u,v;
 6 int p[maxn];
 7 
 8 void init(int n)
 9 {
10     for(int i=1; i<=n; i++)
11         p[i]=i;
12 }
13 
14 int getp(int o)
15 {
16     return p[o]==o?o:(getp(p[o]));
17 }
18 
19 void unio(int u,int v)
20 {
21     int x=getp(u);
22     int y=getp(v);
23     if(x!=y) p[y]=x;
24 }
25 
26 int main()
27 {
28     cin>>t;
29     while(t--)
30     {
31         cin>>n>>m;
32         init(n);
33         int sum=0;
34         for(int i=1; i<=m; i++)
35         {
36             cin>>u>>v;
37             unio(u,v);
38         }
39         for(int j=1; j<=n; j++)
40         {
41             if(p[j]==j)
42                 sum++;
43         }
44         cout<<sum<<endl;
45     }
46     return 0;
47 }

 

E - 数据结构实验之图论九:最小生成树

题目链接 https://acm.sdut.edu.cn/onlinejudge3/contests/3989/problems/E

板子

kruskal

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,cnt,ans;
 4 int p[105];
 5 
 6 struct node
 7 {
 8     int u,v,w;
 9 }edge[10010];
10 
11 bool cmp(node a,node b)
12 {
13     return a.w<b.w;
14 }
15 
16 int getp(int o)
17 {
18     return p[o]==o?o:getp(p[o]);
19 }
20 
21 int kruskal()
22 {
23     for(int i=1; i<=n; i++)
24         p[i]=i;
25     sort(edge+1,edge+m+1,cmp);
26     for(int i=1; i<=m; i++)
27     {
28         int x=getp(edge[i].u);
29         int y=getp(edge[i].v);
30         if(x==y) continue;
31         ans+=edge[i].w;
32         p[y]=x;
33         cnt++;
34         if(cnt==n-1) break;
35     }
36     return ans;
37 }
38 
39 int main()
40 {
41     ios::sync_with_stdio(false);
42     while(cin>>n>>m)
43     {
44         cnt=0;
45         ans=0;
46         for(int i=1; i<=m; i++)
47             cin>>edge[i].u>>edge[i].v>>edge[i].w;
48         kruskal();
49         if(cnt==n-1) cout<<ans<<endl;
50         else cout<<"0"<<endl;
51     }
52     return 0;
53 }

链式前向星版primTLE了?。。。

啊?1999ms?啊?好吧。。。不用你了。

 1 #include<bits/stdc++.h>
 2 #define INF 99999
 3 using namespace std;
 4 int n,m,u,v,w,cnt,tot,ans;
 5 int head[10100];
 6 int dis[10100];
 7 bool vis[105];
 8 
 9 struct node
10 {
11     int v,w,next;
12 } edge[20100];
13 
14 void add(int u,int v,int w)
15 {
16     edge[++tot].v=v;
17     edge[tot].w=w;
18     edge[tot].next=head[u];
19     head[u]=tot;
20 }
21 
22 int prim()
23 {
24     int now=1;
25     for(int i=2; i<=n; i++)
26         dis[i]=INF;
27     for(int i=head[1]; i!=0; i=edge[i].next)
28         dis[edge[i].v]=min(dis[edge[i].v],edge[i].w);
29     while(++cnt<n)
30     {
31         int minn=INF;
32         vis[now]=1;
33         for(int i=1; i<=n; i++)
34         {
35             if(!vis[i] && dis[i]<minn)
36             {
37                 minn=dis[i];
38                 now=i;
39             }
40         }
41         ans+=minn;
42         if(minn==INF) break;
43         for(int i=head[now]; i!=0; i=edge[i].next)
44         {
45             int v=edge[i].v;
46             if(!vis[v] && dis[v]>edge[i].w)
47                 dis[v]=edge[i].w;
48         }
49     }
50     return ans;
51 }
52 
53 int main()
54 {
55     ios::sync_with_stdio(false);
56     cin.tie(NULL);
57     while(cin>>n>>m)
58     {
59         cnt=0;
60         ans=0;
61         if(m!=0)
62         {
63             for(int i=1; i<=m; i++)
64             {
65                 cin>>u>>v>>w;
66                 add(u,v,w);
67                 add(v,u,w);
68             }
69             prim();
70             if(cnt>=n-1) cout<<ans<<endl;
71         }
72         else cout<<"0"<<endl;
73     }
74     return 0;
75 }

 

 

标签:11,SDUTOJ,--,查集,int,init,edge,using,include
来源: https://www.cnblogs.com/marswithme/p/16230296.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有