poj1182(并查集)

时间:2023-03-09 08:36:06
poj1182(并查集)

题目链接

分析:根据分析,关系的递推满足由[a,b]~[b,c]得:[a,c]=([a,b]+[b,c])%3;[a,d]=([a,b]+[b,c]+[c,d])%3.由rank数组表示关系

0 - 这个节点与它的父节点是同类

1 - 这个节点被它的父节点吃

2 - 这个节点吃它的父节点。

则:当 d = 1的时候,( d - 1 ) = 0,也就是我们制定的意义

当 d = 2的时候,( d - 1 ) = 1,代表Y被X吃,也是我们指定的意义。

逆推根节点与Y的关系

这部分也是穷举法推出来的,我们举例:

父相对于子的relation(即假如子是父的父节点,那么父的relation应该是什么,因为父现在是根节点,所以父.relation = 0,我们只能根据父的子节点反推子跟父节点的关系)

0             ( 3 - 0 ) % 3 = 0

1(父吃子)   ( 3 - 1 ) % 3 = 2 //父吃子

2(子吃父)    ( 3 - 2 ) % 3 = 1 //子吃父,一样的

因此合并时,x,y,a(x的根节点),b(y的根节点),d(x与y的关系),rank[x](x与a的关系),rank[y](y与b的关系)rank[b](b与a的关系)则:

[b,a]=([b,y]+[y,x]+[x,a])%3.而[b,y]=(3-[y,b])%3.因此rank[b]=(3-rank[y]+d+rank[x]).

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-9
#define N 50010
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PII pair<int,int>
using namespace std;
int fa[N],rank[N];
int find(int x)
{
if(x==fa[x])return x;
int pa=fa[x];
fa[x]=find(fa[x]);
rank[x]=(rank[x]+rank[pa])%;
return fa[x];
}
void merge(int a,int b,int x,int y,int d)
{
fa[b]=a;
rank[b]=(-rank[y]+d-+rank[x])%;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=; i<=n; i++)
{
fa[i]=i;
rank[i]=;
}
int ans=;
while(m--)
{
int d,x,y;
scanf("%d%d%d",&d,&x,&y);
if(x>n||y>n||(d==&&x==y))ans++;
else
{
int a=find(x);
int b=find(y);
if(a!=b)merge(a,b,x,y,d);
else
{
if((rank[y]+-rank[x])%!=d-)ans++;
}
}
}
printf("%d\n",ans);
}