【Luogu P2024およびP1892]&フードチェーンギャング(ドメインを拡張する互いに素なセット)

P1892 Luogu
Luogu P2024
一見2つの道路、それを見つけるのは簡単で、行うように設定を確認するために使用することができます-しかし、我々は慎重にタイトルを読んで直面したときに、実際には簡単なようではないことがわかります。
私たちは、このようなAの関係が、通常の互いに素セット「友人の友人が私の友人、ある」と「私の敵の敵は友である」の関係を維持することはできません、互いに素セットが簡単であること、情報の推移を維持することができます知っています。
我々はダブルチェックに魔法の操作、およびセットを紹介します今回は、ノードiメンテナンス敵を倍増するために、このスペースを増加します。
例えば、ギャングの問題

    if (c=='F')
        {
            merge(x,y);
        }
        else 
        {
            merge(x,y+n);
            merge(y,x+n);
            //x+n代表的是x的敌人集合
        }

理解することは非常に簡単、実際には非常に効率的な操作です。

P1892完全なコード

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=2001;
int fa[maxn],n,m,cnt,x,y;
int getf(int v)
{
    if (fa[v]==v) return fa[v];
    return fa[v]=getf(fa[v]);
}
inline void merge(int x,int y)
{
    fa[getf(y)]=getf(x);
}
inline bool check(int x,int y)
{
    if (getf(x)==getf(y)) return true;
    return false;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=2*n;i++) fa[i]=i;
    for (int i=1;i<=m;i++)
    {
        char c;
        scanf("\n%c %d %d",&c,&x,&y);
        if (c=='F')
        {
            merge(x,y);
            //merge(x+n,y+n);
            //注意上面这句不能要,因为题目中没有说到朋友的敌人也是我的敌人。
        }
        else 
        {
            merge(x,y+n);
            merge(y,x+n);
        }
    }
    for (int i=1;i<=n;i++) fa[i]=getf(i);//路径压缩,防止压缩不完全
    for (int i=1;i<=n;i++) if (fa[i]==i) cnt++;
    printf("%d\n",cnt);
    return 0;
}

完全なコードP2024

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=3*5*1e4+10;
int fa[maxn],cnt,n,k,flag,x,y;
int getf(int v)
{
    if (fa[v]==v) return v;
    return fa[v]=getf(fa[v]);
}
inline void merge(int x,int y)
{
    x=getf(x);
    y=getf(y);
    fa[x]=y;
}
inline bool check(int x,int y)
{
    x=getf(x);
    y=getf(y);
    if (fa[x]==fa[y]) return true;
    return false;
}
int main()
{
    scanf("%d%d",&n,&k);
    for (int i=1;i<=3*n;i++)
        fa[i]=i;
    //i+n是i吃的集合,i+2n是吃i的集合
    for (int i=1;i<=k;i++)
    {
        scanf("%d%d%d",&flag,&x,&y);
        if (x>n||y>n) {cnt++;continue;}
        if (flag==1)
        {
            if (check(x+n,y)) {cnt++;continue;}
            if (check(x+2*n,y)) {cnt++;continue;}
            merge(x,y);
            merge(x+n,y+n);
            merge(x+2*n,y+2*n);
        }
        if (flag==2)
        {
            if (check(x,y)) {cnt++;continue;}
            if (check(y+n,x)) {cnt++;continue;}
            merge(x+n,y);
            merge(y+2*n,x);
            merge(x+2*n,y+n);
        }
    }
    printf("%d\n",cnt);
    return 0;
}

おすすめ

転載: www.cnblogs.com/notscience/p/11828321.html