众大牛尽情鄙视我吧,是的,我现在才想到我还没有A掉食物链,于是很无语的去写了,然后在很无语的来写个blog.
原本看许多关于并查集的ppt的时候都举了这个例子,一开始以为要维护好多东西,就很烦很烦,然后又看到网上关于这道题的都写得好复杂好复杂,(@.@),就以为要维护好多东西。
the result is----- 我自己想了个ws并查集,A掉之后,以为是多么新奇的方法,发现网上很多都是这么写的(囧..........)
我还是厚着脸皮把我的solution贴上来吧。
其实很明显,动物之间的关系只有三种,而且是有一定的叠加关系的,这里的三种状态直接用1,2,3表示即可。然后,会发现,如果A吃B ,从A 向B 连一条1的边(被吃是2,同类是3),那么在路径压缩的时候顺便把这些值加起来,可以得到结论:如果x 向y 连了边权为c 的边,case c mod 3 of 1:吃 2:被吃 0:同类。
然后并查集裸做就可以了。
program rq455;
const
opp:array[1..3]of longint=(2,1,3);
new1:array[2..6]of longint=(2,1,3,2,1);
new2:array[2..6]of longint=(1,3,2,1,3);
var
i,n,k,d,x,y,fx,fy:longint;
g,fa:array[0..60000]of longint;
ans:longint;
procedure inf;
begin
assign(input,'rq455.in');
assign(output,'rq455.out');
reset(input);rewrite(output);
end;
procedure ouf;
begin
close(input);close(output);
end;
procedure link(x,y,z:longint);
var w:longint;
begin
fa[x]:=y; g[x]:=z;
end;
function find(x:longint):longint;
var k:longint;
begin
if fa[x]<>x then
begin
k:=find(fa[x]);
g[x]:=(g[x]+g[fa[x]]-1) mod 3+1;
fa[x]:=k;
end;
exit(fa[x]);
end;
procedure main;
begin
read(n,k);
for i:=1 to n do begin fa[i]:=i; g[i]:=3; end;
for k:=1 to k do
begin
read(d,x,y);
if (x>n) or (y>n ) then inc(ans)
else if (d=2)and (x=y) then inc(ans)
else
begin
if d=2 then
begin
fx:=find(X); fy:=find(y);
if fx<>fy then
link(fx,fy,new1[g[x]+opp[g[y]]])
else if (g[x]+opp[g[y]]) mod 3<>1 then
inc(ans);
end
else
if d=1 then
begin
fx:=find(x); fy:=find(y);
if fx<>fy then
link(fx,fy,new2[g[x]+opp[g[y]]])
else if (g[x]+opp[g[y]]) mod 3<>0 then
inc(ans);
end;
end;
end;
write(ans);
end;
begin
inf;
main;
ouf;
end.