MuWu大喊:“江南老贼”|月月学长牛逼!

MuWu大喊:“江南老贼”

from CUP oj 学长自出题
时间限制:1s
内存限制:256MB

题目描述:

总所周知,这个世界上龙、混血种势不两立,MuWu是混血种的领袖,当尼德霍格苏醒时,他需要召集全世界的混血种去杀死它。

世界上共有n个混血种组织,第i个组织有a[i]个人,一共有m对组织会相互联系,然而有些组织间可能有些恩恩怨怨,他们之间并不会产生联系。若是两个互不联系的组织间可以通过一个中间组织产生联系,MuWu认为他们之间也可以产生联系。

现在MuWu有q个问题,每个问题下,他问出一个组织,他想知道这个组织最多能联系上多少人(包括自身)。

k对仇怨不深的组织,对于第i对的两个组织x[i]和y[i],MuWu可以花v[i]元钱(混血种都得用RMB)使他们产生联系,MuWu需要花最少的钱使得所有组织都能联系上。

MuWu并不会这些问题,所以他想问下你,你能帮助他吗?

输入:

第一行有三个数n(1≤n≤1e5)和m(0≤m≤1e5),代表n个混血种组织,m个联系。

第二行n个数,第i个数代表a[i]。

后面跟着m行,每行有两个数x(1≤x≤n)和y(1≤y≤n),表示x和y会相互联系。

后面跟着一行,有一个数q(1≤q≤n),代表q个问题。

后面跟着q行,每行一个数,代表MuWu想问该组织可以联系上多少人。

后面跟着一行,有一个数k(1≤k≤1e5),代表k个仇恨不深的联系

后面跟着k行,每行有三个数x(1≤x≤n)和y(1≤y≤n)和v(0≤v≤1e4),表示x和y之间产生联系需要花v元钱。(题目保证最后一定能联系上所有人)

不保证无重边和自环。

输出:

前q行,每行代表一个问题下的答案

最后一行输出最少花多少钱使得所有人都能联系上

样例输入:
6 3
5 6 7 8 9 10
1 2
3 4
3 5
6
1
2
3
4
5
6
4
1 3 5
5 6 6
2 3 2
3 6 5
样例输出:
11
11
24
24
24
10
7

最开始的时候是每个部落都独立存在,然后m行,将一对部落所在集合合并,这里我们建一个数组a[]表示所能联系到的人数,每次合并就将合并过去的根节点的人数累加到合并后的根节点上,这样在后续的q组查询中都是只需要查找一下father就可以了。
经典并查集!

这个题目需要注意好几个地方都可以缩短路径,而且要使用cstdio才行!

AC代码:
#include<cstdio>
#include<algorithm>
using namespace std;
int father[100005];
int a[100005];
int find(int x) {
    if(father[x] == x)
        return x;
    return father[x] = find(father[x]);
}
struct E {
    int f, t, w;
}e[100005];
bool cmp(E a, E b) {
    return a.w < b.w;
}
long long n, m, q, k, all;
int from, to, x, y;
int main() {
    scanf("%d %d",&n,&m), all = n - 1;
    for(int i = 1; i <= n; ++i) scanf("%d",&a[i]), father[i] = i;
    for(int i = 1; i <= m; ++i) {
        scanf("%d %d",&from,&to), x = find(from), y = find(to);
        if(x != y)
            father[x] = y, a[y] += a[x], --all;
    }
    scanf("%d",&q);
    while(q--)
        scanf("%d",&from), printf("%d\n", a[find(from)]);
    scanf("%d",&k);
    long long sum = 0;
    for(int i = 1; i <= k; ++i)
        scanf("%d %d %d",&e[i].f,&e[i].t,&e[i].w);
    sort(e + 1, e + 1 + k, cmp);
    for(int i = 1; all; ++i) {
        x = find(e[i].f), y = find(e[i].t);
        if(x != y) {
            father[x] = y, sum += e[i].w, --all;
        }
    }
    scanf("%d",&sum);
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alan_Lowe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值