SDUTOJ 2021级ACM班&2022年寒假集训《数据结构》专题11--最小生成树、并查集
作者:互联网
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