种类并查集

来源:互联网 发布:公文写作神器软件 编辑:程序博客网 时间:2024/05/17 08:25

HDU 1829     A Bug's Life

这是今天写的第三道并查集,有了前面两道的铺垫,写这一道很快就写完了,网上博客说说这是水题.............暴风哭泣,好吧不管我还是很开心的

题目大体意思就是额? 输入一对x,y表示的是异性关系,而在处理这个关系之前看下是否是同性关系,如果是同性关系的话,那么就是错的 大体就是这样子了

然后嗯 因为不确定每个人到底是女的还是男的所以其实是有两种可能的

那么我们就是设置pre【】为n最大的两倍   之后每次要处理的时候判断下   是否是同性 如果是那么就错了

emmm 理解的关键可能在于有几种可能性,这是我觉得种类并查集理解最最最最关键的一步,我暑假的时候写这个死都不理解。因为根据每种可能性去处理可能发生的事情大体就是这个样子

代码如下:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;const int maxn=4020;int pre[maxn]; int n,m;void init(){for(int i=1;i<=2*n;i++)pre[i]=i;}int ufind(int k) {      if(k==pre[k])    return k;    return pre[k]=ufind(pre[k]);}  void merge(int x,int y){int fx=ufind(x);int fy=ufind(y);if(fx!=fy)pre[fx]=fy;}bool same(int a, int b) {      return ufind(a) == ufind(b);  }  int main(){int t,x,y;scanf("%d",&t);for(int u=1;u<=t;u++){scanf("%d%d",&n,&m);init();int flag=0;while(m--){scanf("%d%d",&x,&y);if(flag)continue;if(same(x,y)||same(x+n,y+n))flag=1; merge(x,y+n);merge(x+n,y);}printf("Scenario #%d:\n",u);if(flag)printf("Suspicious bugs found!\n");else printf("No suspicious bugs found!\n");putchar('\n');}return 0;}



POJ - 1182 

B - 食物链

这题是写种类并查集的第一题,真的特别痛苦记得暑假就做过了,当时也理解得不够透彻后来每次出现种类自己也都不愿意去写这种题目

然后就是开三个数组

0----N-1表示的是在A组    N----2N-1表示的是在B组     2N----3N-1表示得是在C组

因为不确定这个动物到底是在哪一组所以每种情况都是要考虑

当输入的为1的  我们要判断是否是吃与被吃的关系    其实算是

if(same(x,y+n)||same(x,y+2*n))
刚刚尝试了下把

if(same(y,x+n)||same(y,x+2*n))
 调换过来也是ok的嗯~~~~   就是当x是A判断一下他是否是B或者是C

当输入的为2的时候 我们要判断是否是相同的关系或者是被吃的关系

代码:

/*假设A为0----N-1  则B为N---2N-1   C为2N----3N-1; A吃B, B吃C,C吃A。*/ #include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;int pre[150015]; int n;void init(){for(int i=0;i<=3*n;i++)pre[i]=i;} int find(int a)  {      int x=a;      while(pre[x]!=x)      {          x=pre[x];      }      return x;  }  bool same(int n,int m)  {      return find(n)==find(m);  }  void merge(int x,int y)  {        int f1=find(x);        int f2=find(y);        if(f1!=f2)        pre[f1]=f2;  }  int main(){int k,choice,x,y;scanf("%d%d",&n,&k);int ans=0;init();while(k--){scanf("%d%d%d",&choice,&x,&y);if(x>n||y>n||x<1||y<1){ans++;continue;}x=x-1;y=y-1;if(choice==1) //表示同类  所以要先判断他们是x吃y或者是y吃x的关系 {if(same(x,y+n)||same(x,y+2*n))ans++;else {merge(x,y);merge(x+n,y+n);merge(x+2*n,y+2*n);} }else if(choice==2) // 这个要表示的是x吃y  先判断是不是同类 或者说 y吃x {if(same(x,y)||same(x,y+2*n))ans++;else {merge(x,y+n);merge(x+n,y+2*n);merge(x+2*n,y);}}}printf("%d\n",ans);return 0;}


C - Find them, Catch them

 POJ - 1703 


emmm就是判断他是否在相同的团伙中和第一个性别的那个是一个意思的都一样的思路

代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;const int maxn=2*1e5+10; int pre[maxn]; int n,m;int ufind(int k) {      if(k==pre[k])    return k;    return pre[k]=ufind(pre[k]);}  void merge(int x,int y){int fx=ufind(x);int fy=ufind(y);if(fx!=fy)pre[fx]=fy;}bool same(int a, int b) {      return ufind(a) == ufind(b);  }  int main(){int t,x,y;char str[10];scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);    for(int i=0;i<=2*n;i++)    pre[i]=i;while(m--){scanf(" %s%d%d",str,&x,&y);if(str[0]=='D'){merge(x,n+y);merge(n+x,y);}else if(str[0]=='A'){if(same(x,n+y))printf("In different gangs.\n");else if(same(x,y))printf("In the same gang.\n");else printf("Not sure yet.\n");}}}return 0;}





原创粉丝点击