连接:
连接:点击打开打开打开打开链接
题意:
给你n个数 有m个操作,如果op==1 将x和y并到一个集合中去,如果op==2 如果x和y不在一个集合中,就将x从原集合中取出来放到y的集合中去,如果op==3 输出x所在的集合的
元素的个数以及集合中元素的和。
思路 : 并查集的删除操作,这里我们定义一个id数组,在删除操作中我们那个没有真正的删除,而是改变了id数组。这里再开一个sum和num数组分别表示集合中的元素的和 和元素的个数。
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define N 100005
using namespace std;
long long sum[N];
int f[N],id[N],num[N];
int n,m;
void init()
{
int i;
for(i=1;i<=n;i++)
{
sum[i]=(long long)i;
num[i]=1;
f[i]=id[i]=i;
}
return ;
}
int getf(int x)
{
return f[x]==x?x:(f[x]=getf(f[x]));
}
void merge(int x,int y)
{
int t1=getf(id[x]);
int t2=getf(id[y]);
if(t1!=t2){
f[t2]=t1;
sum[t1]+=sum[t2];
num[t1]+=num[t2];
}
return ;
}
void del(int x)
{
int fa=getf(id[x]);
num[fa]--;
sum[fa]-=(long long)x;
id[x]=++n;
num[id[x]]=1;
sum[id[x]]=(long long)x;
f[id[x]]=id[x];
}
int main()
{
int i,j,x,y,op;
while(scanf("%d %d",&n,&m)!=EOF)
{
init();
while(m--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d %d",&x,&y);
merge(x,y);
}
else if(op==2)
{
scanf("%d %d",&x,&y);
int t1=getf(id[x]);
int t2=getf(id[y]);
if(t1!=t2){
del(x);
merge(x,y);
}
}
else{
scanf("%d",&x);
int fa=getf(id[x]);
printf("%d %lld\n",num[fa],sum[fa]);
}
/*
printf("sum: ");
for(i=1;i<=n;i++) printf("%lld ",sum[i]);
printf("\nnum: ");
for(i=1;i<=n;i++) printf("%d ",num[i]);
printf("\n");*/
}
}
return 0;
}
这里还有一种 写法,但是是超时的,虽说过不去,但是对于理解id数组还是有一定的帮助,基本思路是一样的。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define N 100005
using namespace std;
int f[N*3];
int n,m,id;
void init()
{
int i;
for(i=1;i<=n;i++) f[i]=i+n;
for(i=n+1;i<=n+n+m;i++) f[i]=i;
return ;
}
int getf(int x)
{
return f[x]==x?x:(f[x]=getf(f[x]));
}
void merge(int x,int y)
{
int t1=getf(x);
int t2=getf(y);
if(t1!=t2)
{
f[t2]=t1;
}
return ;
}
void del(int x)
{
f[x]=id++;
}
int main()
{
int i,j,op,x,y;
while(scanf("%d %d",&n,&m)!=EOF)
{
init();
id=2*n+1;
while(m--)
{
scanf("%d",&op);
if(op==1){
scanf("%d %d",&x,&y);
merge(x,y);
}
else if(op==2){
scanf("%d %d",&x,&y);
int t1=getf(x);
int t2=getf(y);
if(t1==t2) continue;
del(x);
merge(x,y);
}
else if(op==3)
{
scanf("%d",&x);
int fin;
long long cnt=0;
fin=0;
int fa=getf(x);
for(i=1;i<=n;i++)
{
if(getf(i)==fa){
fin++;
cnt+=(long long)i;
}
}
printf("%d %I64d\n",fin,cnt);
}
/*
printf("fa: ");
for(i=1;i<=n;i++) printf("%d ",getf(i));
printf("\n");*/
}
}
return 0;
}