並查集合集

ZMST發表於2019-01-30

題目1:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1e6+10;
int pre[maxn],maxx[maxn],num[maxn];
int findFather(int x)
{
    int a=x;
    while (x!=pre[x])
    {
        x=pre[x];
    }
    while (a!=pre[a])
    {
        int z=a;
        a=pre[a];
        pre[z]=x;
    }
    return x;
}
void Union(int a,int b)
{
    int faA=findFather(a);
    int faB=findFather(b);
    if(faA!=faB)
    {
        pre[faA]=faB;
        maxx[faB]=max(maxx[faA],maxx[faB]);
        num[faB]+=num[faA];
    }
}
int main()
{
    int n,m;
    while (~scanf("%d%d",&n,&m))
    {
        char str[10];
        for(int i=1;i<=n;i++)
        {
            pre[i]=i;
            num[i]=1;
            maxx[i]=i;
        }
        int Set=n;
        while (m--)
        {
            getchar();
            int x,y;
            scanf("%s",str);
            if(str[0]=='u')
            {
                scanf("%d%d",&x,&y);
                if(findFather(x)!=findFather(y))
                {
                    Union(x, y);
                    Set--;
                }
            }
            if(str[0]=='s'&&str[1]=='a')
            {
                scanf("%d%d",&x,&y);
                if(findFather(x)==findFather(y))
                {
                    puts("1");
                }
                else
                    puts("0");
            }
            if(str[0]=='n')
            {
                scanf("%d",&x);
                printf("%d\n",num[findFather(x)]);
            }
            if(str[0]=='s'&&str[1]=='e')
            {
                printf("%d\n",Set);
            }
            if(str[0]=='m')
            {
                scanf("%d",&x);
                printf("%d\n",maxx[findFather(x)]);
            }
        }
    }
    return 0;
}

題目2:(最小生成樹+並查集)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 110
int father[maxn];
struct node{
    int u,v,data;
}t[maxn];
bool cmp(node a,node b)
{
    return a.data<b.data;
}
int findFather(int x)
{
    while (x!=father[x])
    {
        x=father[x];
    }
    return x;
}
int main()
{
    int n,m;
    while (~scanf("%d%d",&n,&m)&&n!=0)
    {
        memset(father, 0, sizeof(father));
        for(int i=1;i<=m;i++)
        {
            father[i]=i;
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&t[i].u,&t[i].v,&t[i].data);
        }
        sort(t+1, t+1+n, cmp);
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            int faA=findFather(t[i].u);
            int faB=findFather(t[i].v);
            if(faA!=faB)
            {
                father[faA]=faB;
                sum+=t[i].data;
            }
        }
        int cnt=0;
        for(int i=1;i<=m;i++)
        {
            if(father[i]==i)
                cnt++;
        }
        if(cnt==1)
            printf("%d\n",sum);
        else
            printf("?\n");
    }
    return 0;
}

題目3:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 30010
int pre[maxn];
int p[maxn];
int num[maxn];
int FindFather(int x)
{
    int a=x;
    while (x!=pre[x])
    {
        x=pre[x];
    }
    while (a!=pre[a])
    {
        int z=a;
        a=pre[a];
        pre[z]=x;
    }
    return x;
}
void Union(int x,int y)
{
    int faX=FindFather(x);
    int faY=FindFather(y);
    if(faX!=faY)
    {
        pre[faX]=faY;
        num[faY]+=num[faX];
    }
}
int main()
{
    int m,n;
    while (~scanf("%d%d",&m,&n))
    {
        if(m==0&&n==0)
            break;
        memset(num, 0, sizeof(num));
        memset(pre, 0, sizeof(pre));
        for(int i=0;i<m;i++)
        {
            pre[i]=i;
            num[i]=1;
        }
        while (n--)
        {
            int t;
            scanf("%d",&t);
            memset(p, 0, sizeof(p));
            for(int i=0;i<t;i++)
            {
                scanf("%d",&p[i]);
            }
            for(int i=0;i<t-1;i++)
            {
                Union(p[i], p[i+1]);
            }
        }
        int k=FindFather(0);
        printf("%d\n",num[k]);
    }
    return 0;
}

debug了很久,沒有想到runtime error也可能是陣列記憶體不夠大導致的

題目4:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 10010
struct node{
    int u,v;
    double cost;
}a[maxn],b[maxn];
int pre[maxn];
bool cmp(node a,node b)
{
    return a.cost<b.cost;
}
int findFather(int x)
{
    int a=x;
    while (x!=pre[x])
    {
        x=pre[x];
    }
    while (a!=pre[a])
    {
        int z=a;
        a=pre[a];
        pre[z]=x;
    }
    return x;
}
/*int findFather(int x)
{
    int r=x;
    while (r!=pre[r])
        r=pre[r];
    pre[x]=r;
    return r;
}*/
int Union(int x,int y)
{
    int paA=findFather(x);
    int paB=findFather(y);
    if(paA!=paB)
    {
        /*if(paA<paB)
            pre[paB]=paA;
        else*/
            pre[paA]=paB;
        return 1;
    }
    else
        return 0;
}
int main()
{
    int t;
    scanf("%d",&t);
    while (t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&a[i].u,&a[i].v);
        }
        for(int i=0;i<n;i++)
            pre[i]=i;
        int k=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                b[k].u=i;
                b[k].v=j;
                b[k].cost=sqrt((a[i].u-a[j].u)*(a[i].u-a[j].u)+(a[i].v-a[j].v)*(a[i].v-a[j].v));
                k++;
            }
        }
        sort(b, b+k, cmp);
        int cnt=0;
        double sum=0;
        for(int i=0;i<k;i++)
        {
            if((b[i].cost<=1000&&b[i].cost>=10)&&(Union(b[i].u,b[i].v)))
            {
                cnt++;
                sum+=b[i].cost;
            }
            if(cnt==n-1)
                break;
        }
        if(cnt==n-1)
            printf("%.1lf\n",sum*100);
        else
            printf("oh!\n");
    }
    return 0;
}

題目5:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 1010
int pre[maxn];
int findFather(int x)
{
    int a=x;
    while (x!=pre[x])
    {
        x=pre[x];
    }
    while (a!=pre[a])
    {
        int z=a;
        a=pre[a];
        pre[z]=x;
    }
    return x;
}
void Union(int a,int b)
{
    int paA=findFather(a);
    int paB=findFather(b);
    if(paA!=paB)
    {
        pre[paA]=paB;
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    int flag=0;
    while (t--)
    {
        int n,m;
        //if(flag==1)
            //printf("\n");
        scanf("%d%d",&n,&m);
        //flag=1;
        for(int i=1;i<=n;i++)
            pre[i]=i;
        while (m--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            Union(x, y);
        }
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(pre[i]==i)
                cnt++;
        }
        printf("%d\n",cnt);
    }
    return 0;
}

題目6:注意輸入字元吸收空格對輸出的影響,還有就是路徑壓縮過程中移動步數的變化要及時更新

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 10010
int pre[maxn];
int num[maxn];
int cha[maxn];
/*int findFather(int x)
{
    int a=x;
    while (x!=pre[x])
    {
        x=pre[x];
    }
    while (a!=pre[a])
    {
        int z=a;
        a=pre[a];
        pre[z]=x;
    }
    return x;
}*/
int findFather(int x)
{
    if(x!=pre[x])
    {
        int t=pre[x];
        pre[x]=findFather(pre[x]);
        cha[x]+=cha[t];//維護移動陣列
        return pre[x];
    }
    return x;
}
void Union(int a,int b)
{
    int pA=findFather(a);
    int pB=findFather(b);
    if(pA!=pB)
    {
        //if(pA<pB)
        //{
            pre[pA]=pB;
            num[pB]+=num[pA];
        cha[pA]++;
        //}
        //else
        //{
            //pre[pB]=pA;
            //num[pA]+=num[pB];
        //}
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    int cnt=1;
    while (t--)
    {
        int n,q;
        scanf("%d%d",&n,&q);
        printf("Case %d:\n",cnt++);
        for(int i=1;i<=n;i++)
        {
            pre[i]=i;
            num[i]=1;
            cha[i]=0;
        }
        while (q--)
        {
            char c;//[5];
            int x,y;
            getchar();
            scanf("%c",&c);
            //getchar();
            if(c=='T')
            {
                scanf("%d %d",&x,&y);
                Union(x, y);
                //++cha[x];
                //cha[y]++;
            }
            if(c=='Q')
            {
                scanf("%d",&x);
                int k=findFather(x);
                printf("%d %d %d\n",k,num[k],cha[x]);
            }
        }
    }
    return 0;
}

題目7:還有為什麼是聯絡縱座標沒有搞清楚,待考慮

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 500010
int pre[maxn];
struct node{
    int x,y;
}t[maxn];
bool vis[maxn];
int findFather(int x)
{
    if(x==pre[x])
        return x;
    else
    {
        int F=findFather(pre[x]);
        pre[x]=F;
        return F;
    }
}
/*int findFather(int x)
{
    int p=x;
    while(p!=pre[p]) p=pre[p];
    int q;
    while(pre[x]!=p)
    {
        q=pre[x];
        pre[x]=p;
        x=q;
    }
    return p;
}*/
void Union(int a,int b)
{
    int faA=findFather(a);
    int faB=findFather(b);
    if(faA!=faB)
        pre[faA]=faB;
}
bool cmp(node a,node b)
{
    if(a.x!=b.x)
        return a.x>b.x;
    else
        return a.y<b.y;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(vis, 0, sizeof(vis));
        for(int i=1;i<=50000;i++)
        {
            pre[i]=i;
        }
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&t[i].x,&t[i].y);
            vis[t[i].y]=1;
        }
        sort(t, t+n, cmp);
        int prex=-1;
        int prey=-1;
        for(int i=0;i<n;i++)
        {
            if(t[i].x!=prex)
            {
                prex=t[i].x;
                prey=t[i].y;
            }
            else
            {
                Union(prey, t[i].y);//同一橫軸已經統一根,現在就是統一豎軸,所以最後求的是y
            }
        }
        int cnt=0;
        for(int i=1;i<=50000;i++)
        {
            if(vis[i])
            {
            if(pre[i]==i)
                cnt++;
            }
        }
        if(cnt==1)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

 

相關文章