3 条题解

  • 0
    @ 2024-10-9 20:29:08

    提供一个扩展并查集的做法,洛谷有原题。

    i+ni+n 来表示与 ii 相关的另一个值,从而以 2i2i 的空间来维护一个并查集。

    那么如何维护这个并查集呢?只要按照题目的意思就行了。比如 p,qp, q 是朋友,只需要合并 p,qp, q 。而如果是敌人,那么只需要合并 p+n,qp+n, qp,q+np, q+n

    而且敌人的敌人就是朋友,所以也可以套回来。

    int find(int x) { return fa[x]==x ? x : fa[x]=find(fa[x]) ; } // 路径压缩
    
    void link(int x, int y)  // 合并 x,y
    {
        int fx = find(x), fy = find(y);
        fa[fx] = fy;
    }
    
    void solve()
    {
        cin>>n>>m;
        F(i,1,2*n) fa[i] = i;  // 关键初始化
        F(i,1,m){
            char opt; int p,q;
            cin>>opt>>p>>q;
            if (opt=='0') {
                link(p, q); // 不需要合并敌人的原因是,朋友的敌人不一定是自己的敌人。
            }
            if (opt=='1') {
                link(p+n, q); link(q+n, p);
            }
        }
        int ans = 0;
        F(i,1,n) ans += fa[i]==i ; // 这样之后会形成一个森林(每棵树都是并查集建出来的树),只需要统计树根数量。
        cout<<ans<<endl;
    }
    

    信息

    ID
    395
    时间
    1000ms
    内存
    128MiB
    难度
    10
    标签
    递交数
    6
    已通过
    4
    上传者