P2024 食物链

带权并查集。

听bin哥讲课,一开始很不明白(可能是我太弱了),但是后来自己想一想,也就明白带权并查集的实质了。

分析一下:

  设A为父亲节点,B为A的子节点,那么对于以下的三种关系:

    1.A吃B,边权为2。

    2.A被B吃,边权为1。

    3.A和B同种,边权为0。

那么对于w,就有关系式:边权=w-1

有个问题:就是w只有1或者2,那么对于边权为2的边,没办法用w表示,所以在连不能连的边的时候(至于为什么不能连的边要连,一会儿解释),就不能表示从左到右B吃C的情况,只能表示C吃B。所以对于下面的B和C,我们就按C是父亲节点来计算。(而且亿会儿也要假装把B连到C上,那自然C要假装作为B的父亲节点)

       A

B           C

那么有两个关键问题:

1.如果对于x和y已经相连,那么如何判断其关系是否正确。

2.对于没有相连的A,B两棵树(注意:A,B不是根节点),如何相连。

先解决第一个问题:

对于:

     A

B            C

其中假设A,B和A,C已经连了边,而B和C没有连边,现在的操作是w,B,C。

如果这个关系合法,那么就恒有AB=(AC+BC)%3 (别问我怎么证的:暴力枚举所有情况

其中BC=w-1,方向由C——>B(其实这也决定了刚刚恒等式的方向)(至于为什么是C—>B刚刚证了).

对于方向问题其实没那么复杂,因为A->B,2和B->A,1是一样的。对于这里的BC的边权,认为是C到B的,也就说明对于w的描述,我们都要转化成C到B的(就是说下面那个图,是要把左下角的连到右上角的下面)。(反正规定是父亲节点到儿子节点,那么一会儿C也就是父亲节点(B连到C),那么也可证这条边应该按C—>B规定)

那么对于第二个问题:

考虑:

      par[y]

par[x]           | 

 |          y

   x

现在的操作是把x和y连上,我们当然不能连x和y。而应该连par[x],par[y],可是关键问题是并不知道par[x]和par[y]的边权大小,但是其实这个关系是可以求的(已知d[x],d[y],xy)(注意:xy是以y为父亲节点向x方向与x的连线构成的,描述y和x关系的边,xy=w-1)

有恒等式:

d[par[x]]=(d[y]-d[x]+xy)%3 (用到刚刚证的东西了)(其实平行四边形定则也可以,但是我并不会证,用就可以了)

那么为了防止为负,统一要+3,转换后:

d[par[x]]=(d[y]-d[x]+w+2)%3;par[par[x]]=par[y];

那就上代码啦:

#include<cstdio>
using namespace std;
#define maxn 50005
int d[maxn],par[maxn],n,k,ans;
int find(int x)
{
    if(x==par[x])
        return x;
    int t=par[x];
    par[x]=find(par[x]);
    d[x]=(d[t]+d[x])%3;
    return par[x];
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1; i<=n; i++)
        par[i]=i;
    for(int i=1; i<=k; i++)
    {
        int w,x,y;
        scanf("%d%d%d",&w,&x,&y);
        if(x > n || y > n || (w == 2 && x == y ))
        {
            ans++;
            continue;
        }
        if(find(x)==find(y))
        {
            if(d[x]!=(d[y]+w-1)%3)
            {
                ans++;
                continue;
            }
        }
        else
        {
            d[par[x]]=(d[y]+w-d[x]+2)%3;//d[par[x]]=(d[y]+w-1-d[x]+3)%3
            par[par[x]]=par[y];
        }
    }
    printf("%d",ans);
    return 0;
}

 

 

 

posted @ 2018-12-02 14:51  paopo  阅读(64)  评论(0)    收藏  举报