NOI2001 食物链

刚开始看这道题,总感觉可以对这些动物进行染色,令颜色相同的为一类。但是这样是有漏洞的。当你遇到一个没有染过色的动物,你需要给它染什么颜色呢?不能保证结果是正确的。

 

这道题目考查的数据结构是并查集。


用father[n],path[n]数组分别记录当前结点的祖先和到祖先的距离。

这里规定距离为0时为同类,为1时表示被祖先吃,为2时表示吃祖先。

初始时每个元素的祖先是自己,距离为0。


对于每一句话,首先判断是x,y是否大于n,是否出现自己吃自己的情况,满足时讨论如下两种情况。

  1. 如果d=1,表示读入的x和y是同类,这时分别找到x,y和祖先fx,fy,如果fx=fy,说明他们是同一祖先。这时判断x和y到祖先的距离是否相等,显然,不相等证明这是一句假话。如果fx<>fy,说明x和y不在同一集合中,此时将这两个集合合并。合并时可以通过一个简单的向量关系算出fx->fy的距离,即path[fx]=path[y]-path[x].
  2. 如果d=2,表示x吃y,同样的找到它们的祖先,若fx=fy,则根据向量关系判断它们的距离是否矛盾,即检查path[x]-path[y]-2是否为0。若fx<>fy,则类似地根据已有的向量关系算出fx->fy的距离,即 path[fx]=path[y]-path[x]+2.

注意的地方是,因为path在运算过程可能出现负数,为避免这一情况且保证path的性质,可以在每次对path运算后加三再对三取模。
*path数组在维护时要注意,建立新关系时,直接把fx指向fy,相应地修改path值即可,对儿子结点的维护放在getfather函数中进行。

VAR
        FA,D:ARRAY[1..500000]OF LONGINT;
        N,K,DD,X,Y,I,ANS,P,Q:LONGINT;
FUNCTION FIND(X:LONGINT):LONGINT;
 BEGIN
        IF FA[X]=0 THEN EXIT(X);
        FIND:=FIND(FA[X]);
        D[X]:=(D[X]+D[FA[X]])MOD 3;
        FA[X]:=FIND;
 END;
BEGIN
        READLN(N,K);
        FILLCHAR(FA,SIZEOF(FA),0);
        ANS:=0;
        FOR I:=1 TO K DO
                BEGIN
                        READLN(DD,X,Y);
                        IF (X>N) OR (Y>N) THEN
                                BEGIN
                                        INC(ANS);
                                        CONTINUE;
                                END;
                        P:=FIND(X);
                        Q:=FIND(Y);
                        IF DD=1 THEN
                                BEGIN
                                        IF P=Q THEN
                                                BEGIN
                                                        IF D[X]<>D[Y] THEN
                                                                BEGIN
                                                                        INC(ANS);
                                                                        CONTINUE;
                                                                END;
                                                END
                                        ELSE
                                                BEGIN
                                                        FA[P]:=Q;
                                                        D[P]:=(D[Y]-D[X]+3) MOD 3;
                                                END;
                                END
                        ELSE
                                BEGIN
                                        IF P=Q THEN
                                                BEGIN
                                                        IF (2-D[X]+D[Y]) MOD 3<>0 THEN
                                                                BEGIN
                                                                        INC(ANS);
                                                                        CONTINUE;
                                                                END;
                                                END
                                        ELSE
                                                BEGIN
                                                        FA[P]:=Q;
                                                        D[P]:=(D[Y]-D[X]+2) MOD 3;
                                                END;
                                END;
                END;
        WRITELN(ANS);
END.

 

本博客部分引用CSDN MForever大牛博客内容。

posted @ 2011-10-28 10:50  NoRush  阅读(1725)  评论(0编辑  收藏  举报