问题 A: 工作团队(并查集删点操作)

问题 A: 工作团队

时间限制: 1 Sec  内存限制: 128 MB
[提交] [状态]

题目描述

一家公司有n名员工,刚开始每个人单独构成一个工作团队。
有时一项工作仅凭一个人或一个团队难以完成,所以公司会让某两个人所在的团队合并。
但有的工作属于闷声大发财类型的,不适合多人做,所以公司有时也会让一个人从他当前所在的团队中分离出来,构成单独的团队。
公司也要对当前团队的情况进行了解,所以他们也会询问一些问题,比如某两个人是否属于同一工作团队,某个人所在的团队有多少个人,或者当前一共有多少个工作团队。
作为该公司的软件服务商,你的任务便是实现一个实时的操作和查询系统。

输入

每个测试点第一行有两个正整数n ,m ,表示员工数和公司的指令数。
接下来m 行,每行的格式为下列所述之一:
1 u v ,表示将第u个人与第v个人所在的团队合并,如果两个人所在团队相同,则不执行任何操作。
2 w,表示使第w个人从当前的团队中分离出来,如果第w个人不在任何多人团队中,则不执行任何操作。
3 x y ,表示询问x ,y两个人是否在同一个工作团队,是的话回答Yes,否则回答No。
4 z,表示询问第z个人所在的工作团队一共有多少个人。
5,询问当前一共有多少个工作团队。

输出

对每个询问输出一行相应的值表示答案。

样例输入 Copy

3 11
1 1 2
3 2 3
4 2
1 2 3
3 2 3
4 2
5
2 2
3 2 3
4 2
5

样例输出 Copy

No
2
Yes
3
1
No
1
2

提示

 https://blog.csdn.net/DaNIelLAk/article/details/105799415?utm_source=app
一个标准的并查集的题,信息也是比较好维护的,开一个se数组存每个集合的数量,合并的时候 团队 – , 分裂的时候 团队 ++ 。有点难度的话就是怎么样删除一个结点而不影响并查集的结构。显然直接删是删不去的,假如删的是一个集合的跟,也就是 p [ i ] = i 的点,那么以这个点为根点都会受影响,所以肯定是不能直接删掉的。那么可以考虑建立一个虚父节点 fp[N] ,每当查询一个数 x 的时候,都把它映射成 fp [ x ] ,通过这样,就可以保证根节点还存在,删根节点的时候,只需要将其虚父节点改成 tot++ ,再将 p [ tot ] = tot 即可,tot 应该是大于n的数,不能跟原来的冲突,通过这样的处理,当查询根节点的时候,就会映射到 tot ,而查询原来跟根节点在一个集合中的元素的时候,还是会 find 到根节点,完美解决问题。
注意 tot 可能加很多,所以数组要开大点,开小了会超内存?(反正我超了两次。。)
寒假训练的时候做过相似的题:Junk-Mail Filter  HDU - 2473
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
#include<string> 
#include <math.h> 
#include<memory.h>
#include<cstring>
using namespace std; 
using namespace std;
typedef long long ll; 
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int INF=0x3f3f3f3f;
const int maxn=1e6+10;
int pre[maxn]; 
int fpre[maxn];
int se[maxn];
int find(int x){
    if(x!=pre[x]){
        pre[x]=find(pre[x]);
    }
    return pre[x];
}
int n,m;
int cnt,tot;
void inint(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        pre[i]=i; 
        se[i]=1;//每个集团的人数 
        fpre[i]=i; 
    }
    cnt=n,tot=n;
}
int main(){
    inint();
    while(m--){
        int p,l,r;
        p=read();
        if(p==1){
            l=read();
            r=read();
            l=find(fpre[l]);
            r=find(fpre[r]);
            if(l!=r){
                se[r]+=se[l];
                se[l]=0;
                cnt--;
                pre[l]=r;
            }
        }
        else if(p==2){
            l=read();
            int t=find(fpre[l]);
            if(se[t]==1){
                continue;
            }
            fpre[l]=++tot;
            pre[tot]=fpre[l];
            se[tot]=1;
            se[t]--;
            cnt++;
        }
        else if(p==3){
            l=read();
            r=read();
            if(find(fpre[l])==find(fpre[r])){
                printf("Yes\n");
            }
            else{
                printf("No\n");
            }
        } 
        else if(p==4){
            l=read();
            int z=se[find(fpre[l])];
            printf("%d\n",z);
        }
        else{
            printf("%d\n",cnt);
        }
    }
    return 0;
     
}

杭电:

#include"stdio.h"
#include"string.h"

int extra;
struct A
{
    int pre;
    int rep;
}E[1100011];
int hash[1100011];
void build(int n)
{
    int i;
    for(i=0;i<n;i++)
    {
        E[i].pre=i;
        E[i].rep=i;
    }
}
int find(int k)
{
    if(E[k].pre==k)    return k;
    E[k].pre=find(E[k].pre);
    return E[k].pre;
}
void Uninon(int a,int b)
{
    int f1,f2;
    f1=find(a);
    f2=find(b);
    if(f1!=f2)    E[f1].pre=f2;
}
void del(int a)
{
    E[a].rep=extra;
    E[E[a].rep].pre=extra;
    extra++;
}

int main()
{
    int Case=1;
    int n,m;
    int i;
    int a,b;
    char str[5];
    int ans;
    int temp;

    while(scanf("%d%d",&n,&m),n||m)
    {
        build(n);
        extra=n;
        while(m--)
        {
            scanf("%s",str);
            if(str[0]=='M')
            {
                scanf("%d%d",&a,&b);
                Uninon(E[a].rep,E[b].rep);
            }
            else
            {
                scanf("%d",&a);
                del(a);
            }
        }

        memset(hash,0,sizeof(int)*extra);
        ans=0;
        for(i=0;i<n;i++)
        {
            temp=find(E[i].rep);
            if(hash[temp]==0)
            {
                hash[temp]=1;
                ans++;
            }
        }

        printf("Case #%d: %d\n",Case++,ans);
    }
    return 0;
}

 https://www.xuebuyuan.com/1972286.html

猜你喜欢

转载自www.cnblogs.com/lipu123/p/12805931.html