食物連鎖を解くPOJ 1182レポート
問題解決のアイデア:この質問は、パス圧縮およびマージの関係でコレクションを更新する方法では困難である点を示し、他の人のブログ、非常に巧妙なアプローチを読み、同じルートノード0と、1とルートノードポイントが食べていることを示します、 2点が3つだけのケースがあったので、方法の3%との関係を更新することが可能である、食べるためにルートノードで表され、それは非常に便利です。コードを直接見ては、注記を追加しました。最後にTucao直接WAを使用している間、ちょうど逆の問題であるワシントン州の中、nおよびmが、入力しないいくつかの未知の問題について。
#include <stdio.h>
#include<iostream>
#include <algorithm>
#include<string.h>
#include<cmath>
#pragma warning(disable:4996)
#define mod 1000000007
#define ll unsigned long long
const int N = 50005;
using namespace std;
int sum[N];
int father[N];
int find(int x)
{
if (x != father[x])
{
int tem = father[x];//记录上一级
father[x] = find(father[x]);//更新最高上级,即路径压缩
sum[x] = (sum[x] + sum[tem]) % 3;//通过该点和上一级的联系,来更新该点和根节点的联系
}
return father[x];
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
int ans = 0;
memset(sum, 0, sizeof(sum));
for (int i = 0; i <= n; i++)
{
father[i] = i;
}
while (m--)
{
int d, x, y;
scanf("%d%d%d", &d, &x, &y);
if (x > n || y > n)
{
ans++;
continue;
}
else if (2 == d && x == y)
{
ans++;
continue;
}
else
{
int fx = find(x);
int fy = find(y);
if (fx != fy)//说明两个点没有在一颗树上
{
father[fy] = fx;
sum[fy] = (d - 1 + sum[x] - sum[y] + 3) % 3;//现在fx是根节点,通过x和fx的关系更新fy和fx的关系,+3保证数值非负
}
else
{
if (d == 1 && sum[x] != sum[y])
ans++;
if (d == 2 && (sum[x] + 1) % 3 != sum[y])
ans++;
}
}
}
printf("%d\n", ans);
}