解题方法
需要画图 首先把祖先到祖先的距离设置为0 祖先要吃的动物赋值为2 吃祖先的动物为1 为什么这样设置呢!首先所有的动物到祖先距离都为0;
当有动物吃祖先的时候,他到祖先的距离变化为1 当有动物吃这个到祖先距离为1的动物时,这个动物到祖先的距离变成2,如果有动物吃这个到祖先的距离为2的动物时,这个动物到祖先的距离为3;因为这有三种动物,所以第三种动物就是祖先(用%3 的方法就可以更新出这个动物正确的等级)到这里都只能够是判断共祖先的动物是否存在吃与被吃的关系;如果两个不相干的集合要放到一个集合;怎么办呢! 不妨画个图,
这两个图如何合并成一个图呢! 加入存在 这个集合的蛇 吃 这个集合的鸟 看看这个方程 dis[鸟] + 1 + dis[虫祖] == dis[蛇] 这样 第1个集合通过改变祖先的值使得这个祖先的鸟能获取正确的值;因为第一个集合的三个元素的值都增加了1 所以就相当于顺时钟转了一圈,这样答案就对;
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int f[50004],dis[50004];
int find( int x )
{
if( f[x] == x ) return x;
int t = find( f[x] );
dis[x] = ( dis[x] + dis[f[x]] )%3;
f[x] = t;
return t;
}
int main( )
{
int i,u,v,d,ans,N,K;
scanf("%d%d",&N,&K);
for( i = 0; i <= N; i++ )
f[i] = i,dis[i] = 0; ans = 0;
for( i = 1; i <= K; i++ )
{
scanf("%d%d%d",&d,&u,&v);d--;
if( u > N || v > N )
{ans++;continue;}
int a = find( u );
int b = find( v );
if( a == b )
{
if( !d && dis[u] != dis[v] )ans++;
if( d && ( dis[u] - dis[v] == 0 ||
dis[u] - dis[v] == -1 ||
dis[u] - dis[v] == 2
)
) ans++;
}
else
{
f[b] = a;
dis[b] = ( dis[u] - dis[v] - d + 6 )%3 ;
}
}
printf("%d\n",ans);
}