• 续并查集学习笔记——Gang团伙题解


    一言不合先贴题目

    Description

    在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足: 1、 我朋友的朋友是我的朋友; 2、 我敌人的敌人是我的朋友; 所有是朋友的人组成一个团伙。告诉你关于这n个人的m条信息,即某两个人是朋友,或者某两个人是敌人,请你编写一个程序,计算出这个城市最多可能有多少个团伙?

    Input

    第1行为n和m,N小于1000,M小于5000; 以下m行,每行为p x y,p的值为0或1,p为0时,表示x和y是朋友,p为1时,表示x和y是敌人。

    Output

    一个整数,表示这n个人最多可能有几个团伙。

    Sample Input

    6
    4
    E 1 4
    F 3 5
    F 4 6
    E 1 2

    Sample Output

    3

    HINT

    {1},{2,4,6},{3,5}

    一开始的想法和ABC野兽那道题一样,可以维护每个点和祖先的关系。而且似乎更简单。于是有了下面的程序

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int fa[1010],deep[1010],ans[1010][2],n,m;
    int getf(int k){
        if(fa[k]!=k){
            int t=fa[k];
            fa[k]=getf(fa[k]);
            deep[k]=deep[k]+deep[t];
            deep[k]=deep[k]%2;
        }
        return fa[k];
    }
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;++i){
            fa[i]=i;
            deep[i]=0;
        }
        for(int i=1;i<=m;++i){
            char c[2];
            int x,y;
            scanf("%s%d%d",&c,&x,&y);
            if((c[0]=='1')&&(getf(x)!=getf(y))){
                int fx=getf(x);
                int fy=getf(y);
                deep[fx]=(deep[y]-deep[x]+3)%2;
                fa[fx]=fy;
            }
            if((c[0]=='0')&&(getf(x)!=getf(y))){
                int fx=getf(x);
                int fy=getf(y);
                deep[fx]=(deep[y]-deep[x]+2)%2;
                fa[fx]=fy;
            }
        }
        
        for(int i=1;i<=n;++i){
            fa[i]=getf(i);
            //cout<<fa[i]<<" "<<deep[i]<<endl;
            ans[fa[i]][deep[i]]++;
        }
        int add=0;
        for(int i=1;i<=n;++i)
        for(int j=0;j<=1;++j)if(ans[i][j]>0){
            add++;
        }
        
        cout<<add;
        return 0;
    }

    然后、、、、、、就爆0了。

    哪里出了问题?忽然发现题设中并没有:我的敌人的朋友是我的敌人。MDZZ!这不符合逻辑啊,虽然NOI从来不讲逻辑。

    重新出发,想到分点的方法。通过朋友相关联的,fa[x]=y;通过敌人相关联的,fa[x]=y+n,fa[x+n]=y。该题完美解决。楼下程序:

    #include <cstdio>  
    #include <cstring>  
    #include <iostream>  
    #include <algorithm>  
    using namespace std;  
    int n,m,ans,a[1010];  
    int fa[2020];  
    int Find(int x)  {  
        if(!fa[x]||fa[x]==x)  
        return fa[x]=x;  
        return fa[x]=Find(fa[x]);  
        }  
    void Union(int x,int y)  {  
        x=Find(x);y=Find(y);  
        if(x==y) return ;  
        fa[x]=y;  
        }  
    int main(){  
        int i,x,y;  
        char p[10];  
        cin>>n>>m;  
        for(i=1;i<=m;i++)  
        {  
            scanf("%s%d%d",p,&x,&y);  
            if(p[0]=='F')  
                Union(x,y);  
            else  
                Union(x,y+n),Union(x+n,y);  
        }  
        for(i=1;i<=n;i++)  
            a[i]=Find(i);  
        sort(a+1,a+n+1);  
        for(i=1;i<=n;i++)  
            if(i==1||a[i]!=a[i-1])  
                ++ans;  
        cout<<ans<<endl;  
        return 0;  
    }  

    To be continue......

  • 相关阅读:
    【学习笔记】QT下载地址
    【学习笔记】激活码方式注册的实现原理述
    【学习笔记】Inputs on an Embedded Linux Device
    【学习笔记】TSlib校准原理
    【学习笔记】13.5 使用者的特殊 shell 与 PAM 模块
    【学习笔记】Linux GDM
    【学习笔记】MC.exe 生成H和RC文件
    【工具】时间差计算器
    【学习笔记】Android 学习(一)
    【学习笔记】tensor flow 2.4 moist 数据下载错误
  • 原文地址:https://www.cnblogs.com/cxl681237/p/6164073.html
Copyright © 2020-2023  润新知