重点依旧是用rank记录相对于根节点的关系,并及时跟新rank的值。
code:
#include<cstdio>
using namespace std ;
int f[50001] ;
int r[50001] ;//与根节点的关系
int find_Set(int x){
int temp ;
if(x==f[x])
return x ;
temp = f[x] ;
f[x] = find_Set(temp) ;
r[x] = (r[temp]+r[x]) % 3 ;
/*
r[x]是相对于x原根节点temp的关系值,现在相对根节点已不是temp
故更新r[x]值时要加上temp相对于其根节点的差值r[temp]
递归调用,查找一次x可将在其前入集的点全部更新
*/
return f[x] ;
}
void Union(int x, int y, int fx, int fy, int d){
f[fy] = fx ;
r[fy] = (d+2+r[x]-r[y]) % 3 ;
/*
r[]为此元素与根节点关系,1为被吃,2为吃
find_set()后,如果x已经入集,则fx为根节点,若未入,则fx为其本身
无论哪种情况r[fx],r[fy]均为0
将fx作为根节点,则r[x]不变,因为r[fx]恒为0
若x吃y,则r[y] = r[x]+1
若为同类,则r[y] = r[x]+0
列表可得出r[fy]的改变量
*/
}
int main(){
int n, k, i, d, x, y, fail, fx, fy ;
scanf("%d%d", &n, &k) ;
fail = 0 ;
for(i=0; i<=n; i++){
f[i] = i ;
r[i] = 0 ;
}
for(i=0; i<k; i++){
scanf("%d%d%d", &d, &x, &y) ;
if(x>n||y>n||(d==2&&x==y)){
fail ++ ;
//printf("%d %d\n", x, y) ;
continue ;
}
fx = find_Set(x) ;
fy = find_Set(y) ;
if(fx!=fy)
Union(x, y, fx, fy, d) ;
else{
if(d==1&&r[x]!=r[y]){//与root关系不同
fail ++ ;
//printf("%d %d\n", x, y) ;
}
if(d==2&&(r[x]-r[y]+3)%3!=2){//列举x吃y情况下r所有可能,得出结论
fail ++ ;
//printf("%d %d\n", x, y) ;
}
}
}
printf("%d\n", fail) ;
return 0 ;
using namespace std ;
int f[50001] ;
int r[50001] ;//与根节点的关系
int find_Set(int x){
int temp ;
if(x==f[x])
return x ;
temp = f[x] ;
f[x] = find_Set(temp) ;
r[x] = (r[temp]+r[x]) % 3 ;
/*
r[x]是相对于x原根节点temp的关系值,现在相对根节点已不是temp
故更新r[x]值时要加上temp相对于其根节点的差值r[temp]
递归调用,查找一次x可将在其前入集的点全部更新
*/
return f[x] ;
}
void Union(int x, int y, int fx, int fy, int d){
f[fy] = fx ;
r[fy] = (d+2+r[x]-r[y]) % 3 ;
/*
r[]为此元素与根节点关系,1为被吃,2为吃
find_set()后,如果x已经入集,则fx为根节点,若未入,则fx为其本身
无论哪种情况r[fx],r[fy]均为0
将fx作为根节点,则r[x]不变,因为r[fx]恒为0
若x吃y,则r[y] = r[x]+1
若为同类,则r[y] = r[x]+0
列表可得出r[fy]的改变量
*/
}
int main(){
int n, k, i, d, x, y, fail, fx, fy ;
scanf("%d%d", &n, &k) ;
fail = 0 ;
for(i=0; i<=n; i++){
f[i] = i ;
r[i] = 0 ;
}
for(i=0; i<k; i++){
scanf("%d%d%d", &d, &x, &y) ;
if(x>n||y>n||(d==2&&x==y)){
fail ++ ;
//printf("%d %d\n", x, y) ;
continue ;
}
fx = find_Set(x) ;
fy = find_Set(y) ;
if(fx!=fy)
Union(x, y, fx, fy, d) ;
else{
if(d==1&&r[x]!=r[y]){//与root关系不同
fail ++ ;
//printf("%d %d\n", x, y) ;
}
if(d==2&&(r[x]-r[y]+3)%3!=2){//列举x吃y情况下r所有可能,得出结论
fail ++ ;
//printf("%d %d\n", x, y) ;
}
}
}
printf("%d\n", fail) ;
return 0 ;
}