zoukankan      html  css  js  c++  java
  • 洛谷P2024食物链——并查集补集的灵活运用

    题目:https://www.luogu.org/problemnew/show/P2024

    自己在做本题时最大的障碍就是:不会在一个集合的father改变时把相应的补集也跟着改变。

    借鉴题解后,才明白原来就是把其补集也进行合并;由于fa数组在改变,不要定义一个变量为原来的find()在后面使用。

    原来的乱七八糟代码:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,k,s;
    int fa[2000005];
    int find(int x)
    {
        if(x==fa[x])return x;
        return fa[x]=find(fa[x]);
    }
    int main()
    {
        scanf("%d%d",&n,&k);
    //	for(int i=1;i<=n;i++)
    //		fa[i]=i;
        int a,b,c;
        for(int i=1;i<=k;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(b>n||c>n)
            {
                s++;continue;
            }
            if(a==1)
            {
                if(!fa[b])
                {
                    if(!fa[c])
                        fa[b]=b,fa[c]=b;
                    else fa[b]=c;
                }
                else if(!fa[c])fa[c]=b;
                else
                {
                    int u=find(b);
                    int v=find(c);
                    if(u==find(v+n)||u==find(v+2*n)||
                        v==find(u+2*n)||v==find(u+n))s++;
                    else fa[u]=v;
                }
            }
            if(a==2)
            {
                if(b==c)
                {
                    s++;continue;
                }
                if(!fa[b])fa[b]=b;
                if(!fa[c])fa[c]=c;
                int u=find(b);
                int v=find(c);
                if(u==v||u==find(v+n)||v==find(u+2*n))s++;
                else fa[v]==u+n,fa[u]=v+2*n;
            }
        }
        printf("%d",s);
        return 0;
    }
    

      改进后的代码(AC):

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,k,s;
    int fa[2000005];
    int find(int x)
    {
        if(x==fa[x])return x;
        return fa[x]=find(fa[x]);
    }
    int main()
    {
        scanf("%d%d",&n,&k);
    	for(int i=1;i<=n*3;i++)//!!
    		fa[i]=i;
        int a,b,c;
        for(int i=1;i<=k;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(b>n||c>n)
            {
                s++;continue;
            }
            if(a==1)
            {
    //            int u=find(b);
    //            int v=find(c);
    			if(find(b)==find(c+n)||find(b+n)==find(c))s++;
    			else
    //			 fa[b]=c;
    			{
    				fa[find(b)]=fa[find(c)];//!!!
    				fa[find(b+n)]=fa[find(c+n)];//!!!
    				fa[find(b+2*n)]=fa[find(c+2*n)];//!!!
    			}
            }
            if(a==2)
            {
    //            int u=find(b);
    //            int v=find(c);
    			if(b==c||find(b)==find(c)||(find(c+n)==find(b)))s++;
    			else
    //			 fa[b+n]=c,fa[c+2*n]=b;
    			{
    				fa[find(b+n)]=fa[find(c)];//!!!
    				fa[find(c+2*n)]=fa[find(b)];//!!!
    				fa[find(b+2*n)]=fa[find(c+n)];//!!!
    			}
            }
    //        for(int i=1;i<=n;i++)
    //        	printf("fa[%d]=%d ",i,fa[i]);
    //        cout<<endl;
        }
        printf("%d",s);
        return 0;
    }
    /*
    4 5
    1 1 3
    2 2 4
    2 3 2
    1 1 4
    2 2 3
    
    2
    */
    

      

  • 相关阅读:
    C# 委托应用总结
    C语言指针总结
    SQL2005四个排名函数(row_number、rank、dense_rank和ntile)的比较
    C#接口
    C# Linq
    C#反射
    重写与重载
    mysql01
    ajax
    bootstrap02导航菜单
  • 原文地址:https://www.cnblogs.com/Zinn/p/8245562.html
Copyright © 2011-2022 走看看