设为首页 加入收藏

TOP

HDU 1829 && POJ 2492 A Bug's Life(种类并查集)
2015-07-20 17:34:21 来源: 作者: 【 】 浏览:2
Tags:HDU 1829 & POJ 2492 Bug' Life 种类 查集

题目地址:HDU 1829 POJ 2492

这个题可以用两种方法做,第一眼看完题是觉得用dfs染色判断二分图。然后又写的刚学的种类并查集。原来并查集可以这样用,真是神奇。。

dfs染色代码:

#include 
  
   
#include 
   
     #include 
    
      #include 
     
       #include 
      
        #include 
       
         #include 
        
          #include 
         
           #include 
           #include 
           
             #include 
            
              using namespace std; int vis[3000], head[3000], cnt, flag; struct node { int u, v, next; } edge[2010000]; void add(int u, int v) { edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } void dfs(int u) { int i; if(flag) return ; for(i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; if(!vis[v]) { vis[v]=-vis[u]; dfs(v); } else { if(vis[v]==vis[u]) { flag=1; return ; } } } } int main() { int n, m, i, t, u, v, num=0; scanf("%d",&t); while(t--) { num++; scanf("%d%d",&n,&m); memset(head,-1,sizeof(head)); cnt=0; while(m--) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } memset(vis,0,sizeof(vis)); flag=0; for(i=1; i<=n; i++) { if(!vis[i]) { vis[i]=1; dfs(i); } } printf("Scenario #%d:\n",num); if(flag) puts("Suspicious bugs found!\n"); else puts("No suspicious bugs found!\n"); } return 0; }
            
           
         
        
       
      
     
    
   
  

下面一种方法是种类并查集。终于明白原理是为什么了。

种类并查集是给每个结点一个权值。然后在合并和查找的时候根据情况对权值来进行维护。

对于这个题来说,就可以给每个节点设置一个0或1的权值。0代表与根节点同性,1代表与根节点异性。

与根节点的关系可以在查找的时候利用递归从根节点向叶子不断进行维护。利用抵消的原理,不断相加余2就行了。

然后合并的时候,由于根节点的性别是不确定的,不能简单简单的合并就完了,还要考虑两颗树的根节点之间的关系。这时候,要想使两个异性结点一个为0一个为1,只要将被合并的那棵树的根节点维护一下就可以,下面的所有的结点的值都可以在查找的时候由这个根节点来决定。因为,如果根节点为0,那么下面的都不会改变,如果为1的话,那下面的都会改变。剩下的就是考虑这个根节点要怎么确定。

要想使输入两个异性结点一个为0一个为1,假如此时在两颗树中显示的是同性,那么只要把根节点设置成1,否则,就设置成0.这地方应该很好想,就不解释了。这时可以用两者权值之和加1余2来实现。

代码如下:

#include 
  
   
#include 
   
     #include 
    
      #include 
     
       #include 
      
        #include 
       
         #include 
        
          #include 
         
           #include 
           #include 
           
             #include 
            
              using namespace std; int bin[3000], rank[3000]; int find1(int x) { int y; if(bin[x]!=x) { y=bin[x]; bin[x]=find1(bin[x]); rank[x]=(rank[y]+rank[x])%2; } return bin[x]; } int join(int x, int y) { int f1=find1(x); int f2=find1(y); if(f1==f2) { if(rank[x]==rank[y]) return 1; } else { bin[f2]=f1; rank[f2]=(rank[x]+rank[y]+1)%2; } return 0; } int main() { int n, m, i, t, flag, num=0, a, b; scanf("%d",&t); while(t--) { num++; flag=0; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { bin[i]=i; rank[i]=0; } while(m--) { scanf("%d%d",&a,&b); if(flag) continue ; if(join(a,b)) flag=1; } printf("Scenario #%d:\n",num); if(flag) puts("Suspicious bugs found!\n"); else puts("No suspicious bugs found!\n"); } return 0; } 
            
           
         
        
       
      
     
    
   
  


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇HDU 5037(Frog-贪心青蛙跳石子) 下一篇BZOJ 1672 Usaco 2005 Dec Cleani..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·在 Redis 中如何查看 (2025-12-26 03:19:03)
·Redis在实际应用中, (2025-12-26 03:19:01)
·Redis配置中`require (2025-12-26 03:18:58)
·Asus Armoury Crate (2025-12-26 02:52:33)
·WindowsFX (LinuxFX) (2025-12-26 02:52:30)