poj 1182 食物链并查集

来源:互联网 发布:ubuntu16安装php 编辑:程序博客网 时间:2024/06/05 10:25

这道题提交了三次吧,每次都wrong,究其原因,前几次都是因为单组输入而不是多组输入,所以while(scanf("%d")!=EOF)这样写是错的。

后来检查发现,查找函数漏了一种情况,补上之后AC。

再来说下思路:

(1):这道题要想用并查集做出来,关键在于懂的用偏移量来表示节点与根节点之间的关系,比如用0表示与根节点同类,用1表示吃根节点,用2表示被根节点吃。

(2):初始化注意点就行。

(3)这道题复杂在要推出节点与节点之间的关系是怎么样的

 网上好像都有公式,我是自己算的,然后找规律竟可能的用简洁的代码写出来。。

#include <iostream>
#include <stdio.h>
#define N 800000
using namespace std;
int f[N],c[N],cnt;
int find(int x)
{
  if(f[x]==x)return x;
  int t=f[x];
     f[x]=find(f[x]);
     c[x]=(c[x]+c[t])%3;
     return f[x];
}
void make(int a,int b,int d)
{
 int f1=find(a);
 int f2=find(b);
 if(f1!=f2)
 {
   f[f1]=f2;
   if(d==2)
   {
     if(c[a]==0)
        c[f1]=(c[b]+1)%3;
     else if(c[a]==1)
        c[f1]=c[b];
     else if(c[a]==2)
        c[f1]=(c[b]+2)%3; 
   }
   else if(d==1)
   {
     if(c[a]==0)
        c[f1]=c[b];
     else if(c[a]==1)
        c[f1]=(c[b]+2)%3;
     else if(c[a]==2)
        c[f1]=(c[b]+1)%3;     
    }  
 }
 else
 {
   if(d==1&&c[a]!=c[b])
     cnt++;
   else if(d==2)
   {
     if(c[a]==0&&c[b]!=2)
        cnt++;
     else if(c[a]==1&&c[b]!=0)
        cnt++;
     else if(c[a]==2&&c[b]!=1)
        cnt++;
   }   


 }
}
int main()
{
  int n,m;
  int d,x,y;
  scanf("%d%d",&n,&m);
  cnt=0;
  memset(c,0,sizeof(c));
  for(int i=1;i<=n;i++)
        f[i]=i;
  for(int i=0;i<m;i++) 
  {
    scanf("%d%d%d",&d,&x,&y);
     if(x>n||y>n)
     {
       cnt++;
       continue;  
     }
     if(d==2&&x==y)
     {
       cnt++;
       continue;  
     }
     make(x,y,d);
  }
  printf("%d\n",cnt);
 
 return 0;   
}

0 0
原创粉丝点击