A Bug's Life(加权并查集)
Description
Input
Output
Sample Input
2
3 3
1 2
2 3
1 3
4 2
1 2
3 4
Sample Output
Scenario #1: Suspicious bugs found! Scenario #2: No suspicious bugs found!
题目意思:t组数据,n个虫子,m组相互喜爱的关系,虫子分为雌雄两种,每个虫子只有一个性别,问是否存在同性恋的虫子。
解题思路:一开始我的思路是希望通过将虫子划分为雌雄两个集合,看看这两个集合中是否出现了环,出现了环则说明存在着同性恋。我看了看网上的题 解,给出了加权并查集的概念,这里我就试着使用这个思想来解题。
加权并查集: 有的时候,不仅需要像普通并查集一样记录一些元素之间有无关系,还需要记录它们之间有怎样的关系,这时候就需要引入加权并查集。 通常情况下,用一个数组r来记录这些关系,r[i]表示元素i与父结点的关系。至于是什么关系,还要根据具体要求来看。 在find(x)函数中进行路径压缩的同时,许多结点的父结点会改变,这时就需要根据实际情况调整权值以保证其正确性。 在union(x,y)函数中,(不妨设将y集合并入x集合)由于y的父结点的改变,需要调整y对应的权值,但不需要调整y的子结点对应的权值,因为子结点 权值会在find(子结点)时得到调整。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int pre[20010]; 6 int r[20010];///r=0代表与根节点同性 7 int Find(int x) 8 { 9 int t; 10 if(pre[x]==x) 11 { 12 return x; 13 } 14 t=pre[x]; 15 pre[x]=Find(pre[x]);///压缩路径 16 r[x]=(r[x]+r[t]+1)%2; 17 return pre[x]; 18 } 19 void Union(int a,int b) 20 { 21 int x,y; 22 x=Find(a); 23 y=Find(b); 24 pre[x]=y; 25 r[x]=(r[b]-r[a])%2; 26 } 27 int main() 28 { 29 int t,i,j,k,flag; 30 int n,m,a,b; 31 scanf("%d",&t); 32 for(k=1;k<=t;k++) 33 { 34 flag=0; 35 scanf("%d%d",&n,&m); 36 for(i=1; i<=n; i++) 37 { 38 r[i]=1; 39 pre[i]=i; 40 } 41 for(i=1; i<=m; i++) 42 { 43 scanf("%d%d",&a,&b); 44 if(Find(a)==Find(b)) 45 { 46 if(r[a]==r[b])///同性 47 { 48 flag=1; 49 } 50 } 51 else 52 { 53 Union(a,b); 54 } 55 } 56 if(flag) 57 { 58 printf("Scenario #%d:\nSuspicious bugs found!\n\n",k); 59 } 60 else 61 { 62 printf("Scenario #%d:\nNo suspicious bugs found!\n\n",k); 63 } 64 } 65 return 0; 66 }
本文作者:王陸
本文链接:https://www.cnblogs.com/wkfvawl/p/9810784.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步