poj 1182 食物链
分析
并查集,需要维护集合内元素与根节点的关系(吃?被吃?同类)
有点类似向量的想法
如果x y属于同一集合
如果x y不属于同一集合
dis[x]=0表示x与根节点同类,1表示根节点吃x,2表示x吃根节点.
1 #include<cstdio> 2 #include<cstring> 3 #define N 50010 4 using namespace std; 5 int root[N],dis[N],n,m; 6 void init(){ 7 for(int i=1;i<=n;i++){ 8 root[i]=i; 9 dis[i]=0; 10 } 11 } 12 int find(int x){ 13 if(x==root[x])return x; 14 int rx=root[x]; 15 root[x]=find(root[x]); 16 dis[x]=(dis[x]+dis[rx])%3; 17 return root[x]; 18 } 19 int main(){ 20 scanf("%d%d",&n,&m); 21 init(); 22 int ans=0; 23 while(m--){ 24 int d,x,y; 25 scanf("%d%d%d",&d,&x,&y); 26 if(x>n||y>n){ 27 ++ans; 28 continue; 29 } 30 if(d==1){ 31 if(find(x)!=find(y)){ 32 dis[root[x]]=(dis[y]-dis[x]+3)%3;//注意这两句的更新顺序... 33 root[root[x]]=root[y]; 34 } 35 else{ 36 if((dis[y]-dis[x]+3)%3) 37 ++ans; 38 } 39 } 40 else{ 41 if(find(x)!=find(y)){ 42 dis[root[x]]=(dis[y]-dis[x]+4)%3; 43 root[root[x]]=root[y]; 44 } 45 else{ 46 if((dis[y]+1-dis[x]+3)%3) 47 ++ans; 48 } 49 } 50 } 51 printf("%d\n",ans); 52 53 return 0; 54 }