BUPT Summer Journey #test4 B


时间限制 3000 ms 内存限制 65536 KB

题目描述

田田家开了一家大公司,面对现在的形势,很多公司选择了联盟。联盟一旦成立就意味着联盟内的每个公司互相之间都认可结盟。所以当决定以一家公司为对手的时候就一定要计算出这家公司所在联盟的总实力值来决定有没有能力击败对手。
现在有n个公司,和m条信息。每条信息可能是某两个公司宣布联盟或者查询某个公司所在联盟的实力值

输入格式

多组数据
第一行为数据量T,每个case第一输入n,m ,之后一行输入n个数ai表示第i个公司的实力值,之后m行输入信息,有两种信息

第一种为两个公司联盟,该行为1 x y ,1表示联盟操作,即x,y两个公司联盟,

第二种为查询某个公司,该行为2 x,2表示查询操作,即查询x公司所在联盟的实力值;

T<=10
n,m<=10^5
ai<=10^6

输出格式

每个查询一行输出,输出那个公司联盟的实力值

输入样例

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

输出样例

3
5
6
思路:由于一个公司的人有一个实力值,范围N,M10^5,如果真的直接查找统计会很麻烦。这题运用并查集,将每一个公司的实力值保存在父亲的根节点上,再访问根节点得到实力值即可。注意合并的时候要判断两个父亲是否相等,不要重复累加.

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define maxn 200000
//#define LOCAL
using namespace std;
int n,m,kind,x,y;
int father[maxn];
double a[maxn],sum[maxn];
int getfather(int x)
{
    if(x==father[x])return x;
    return father[x]=getfather(father[x]);
}
void Union(int x,int y)
{
    int f1=getfather(x),f2=getfather(y);
    if(f1!=f2)
    {
        father[f2]=f1;sum[f1]=sum[f1]+sum[f2];
    }
}
int main()
{
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    #endif // LOCAL
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);//cout<<n<<' '<<m<<endl;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n;i++){father[i]=i;sum[i]=a[i];}
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&kind);
            if(kind==1){scanf("%d%d",&x,&y);Union(x,y);/*cout<<getfather(x)<<' '<<getfather(y)<<endl;cout<<sum[getfather(x)]<<' '<<sum[getfather(y)]<<endl;*/}
            if(kind==2){scanf("%d",&x);printf("%lld\n",sum[getfather(x)]);}
        }
        //for(int i=1;i<=n;i++)printf("%lld ",sum[i]);
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值