题目
题解思路
参考上一篇文章中大佬的带权并查集博客
感觉这题能用一般并查集写,想了很久还是没有思路,换成带权并查集还是卡了很久。结果这题大佬讲了。
运用模运算使权值的都在3一下,这样就可以代表分别输入哪个种类。
再运用权值相减来判断是否合法。
手模了几次。
代码像是在维护一棵2层的树或者3层的树。
一颗树树顶只有一个源点。
当值没在树里是无法判断的,就有先合并进树的操作。
这题卡cin和多组。
AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int a[50100];
int w[50100];
int find2(int x)
{
if ( x != a[x] )
{
int t = a[x];
a[x] = find2(a[x]);
w[x] = (w[x] + w[t] )%3;
}
return a[x];
}
int main ()
{
int n,k,ans = 0;
scanf("%d%d",&n,&k);
for ( int i = 1 ;i <= n ; i++ )
a[i] = i;
for (int i = 1 ;i <= k ; i++ )
{
int b,c,d;
scanf("%d%d%d",&b,&c,&d);
if ( c > n || d > n || ( c == d && b == 2 ) )
{
ans++;
}else
{
int fx = find2(c);
int fy = find2(d);
if ( fx == fy )
{
if ( b - 1 != (w[c]-w[d]+3)%3 )
{
ans++;
}
}else
{
a[fx] = fy;
w[fx] = ( -w[c] + b-1 + w[d] )%3 ;
}
}
}
printf("%d\n",ans);
return 0;
}