公司竞争(并查集)
学长毕业啦!
学长自己开了一家大公司,现在很多公司选择了联盟。所以当决定和一家公司竞争的时候就要和联盟内所有公司竞争。
盟友关系是有传递性的。即 A 和 B 成为盟友,那么就会和 B 现有的其他盟友也成为盟友。
每个公司都有势力值。而联盟的势力值是所有联盟内公司的总和。
输入格式
第一行有两个数 n和 m。(1≤n,m≤10^5)
第二行有
n个整数,代表每个公司的势力值,不超过 10^3。
以后 m行代表 m 个事件:1 x y代表公司 x和公司 y结盟。
2 x 代表学长询问公司 x 所在的联盟的势力值。
输出格式
对于每一次询问输出一行,为所在的联盟的势力值。
Sample Input
5 5
1 2 3 4 5
1 1 2
2 2
2 5
1 2 3
2 1
Sample Output
3
5
6
思路: 经典并查集,不好写的地方为如何累加势力值,代码解释
AC代码:
#include<stdio.h>
#include<string.h>
int e[110000],f[110000],n,m;
void init()
{
int i;
for(i=1; i<=n; i++)
f[i]=i;
}
int find(int x)
{
if(f[x]==x)
return x;
else
return f[x]=find(f[x]);
}
void merge(int x,int y)
{
int xx,yy;
xx=find(x);
yy=find(y);
if(xx!=yy)
{
f[yy]=xx;
e[xx]=e[xx]+e[yy];//只把综合势力值赋值给head,以防少加,多加
}
}
int main()
{
int i,j,k,c,a,b;
scanf("%d%d",&n,&m);
init();
for(i=1; i<=n; i++)
scanf("%d",&e[i]);
while(m--)
{
scanf("%d",&c);
if(c==1)
{
scanf("%d%d",&a,&b);
merge(a,b);
}
if(c==2)
{
scanf("%d",&k);
int x=find(k);//寻找k的head,输出head的势力值
printf("%d\n",e[x]);
}
}
return 0;
}