第一种是看的有些博客的解法, 也很好,并且用时和带权并查集差不多。
第二种是带权并查集, 思路是按照每个节点和根节点的距离进行分类,总共有三种,所以% 3 就可以了 。
想当初一个月前看这个题是那么的难,现在看来还挺简单的, 我真的成长了呢~
#include <iostream>
#include <cstring>
using namespace std;
const int N = 50010;
int p[3 * N], n, m, sum;
int find(int x)
{
int j = x, i = x;
while (p[j] != -1) j = p[j];
//cout << j << endl;
while (p[i] != -1)
{
int t = p[i];
p[i] = j, i = t;
}
return j;
}
void un(int a, int b)
{
int x = find(a), y = find(b);
if (x != y) p[x] = y;
}
bool same(int a, int b)
{
if (find(a) == find(b)) return true;
return false;
}
int main()
{
cin >> n >> m;
memset(p, -1, sizeof p);
while (m--)
{
int d, a, b; scanf("%d %d %d", &d, &a, &b);
if (a > n || b > n)
{
sum++; continue;
}
if (d == 1)
{
if (same(a, b + n) || same(a, b + 2 * n)) sum++;
else
{
un(a, b); un(a + n, b + n); un(a + 2 * n, b + 2 * n);
}
}
else
{
if (same(a, b) || same(a, b + 2 * n)) sum++;
else
{
un(a, b + n); un(a + n, b + 2 * n); un(a + 2 * n, b);
}
}
//cout << m << endl;
}
cout << sum << endl;
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
const int N = 200010;
int p[N], d[N], m, n, sum;
int find(int x)
{
if(p[x] == -1) return x;
else
{
int t = p[x];
p[x] = find(p[x]);
d[x] += d[t];
}
return p[x];
}
int main()
{
cin >> n >> m;
memset(p, -1, sizeof p);
while(m --)
{
int t, a, b; scanf("%d %d %d", &t, &a, &b);
if(a > n || b > n)
{
//cout << a << endl;
sum ++; continue;
}
int x = find(a), y = find(b);
if(x != y)
{
p[x] = y;
d[x] = (d[b] - d[a] - t + 1);
//cout << d[x] << " " << a << b << endl;
}
else
{
if(((t - 1 + d[a]) % 3 + 3) % 3 != (d[b] % 3 + 3) % 3)sum ++;
}
}
cout << sum << endl;
return 0;
}