列表

详情


KS30. 情报

描述

Brotherhood在KWAI建立了分部,但由于燕大人杰地灵,不是什么人都能够任意进出的,于是现在一个棘手的问题摆在了Ezio面前:情报的传递。

已知燕大内的Brotherhood一共有 n 个团体,有些团体之间有一些关系,你可以把它们看作一条边,每条边连接了两个 **不同** 的团体,现在一共有 m 条边。

现在前辈 Jumbo 要求 Ezio 将一个情报传递给燕大内的所有团体。已知 Ezio 亲自去向团体i告知情报的代价为 val[i] 。Ezio 当然不想一个一个去找啦,他还有很多任务要完成,于是他发现他可以利用团体之间的关系,让某一个已经被传达过情报的团体去告知另一与之有关系团体。

但是团体内部的人懒癌发作,自然不想白白地去帮 Ezio跑 腿。具体来说,针对关系 (u,v) ,如果 Ezio 想要利用它,应该付出的代价为cost(u,v)。

简而言之:
一个团体得到情报有两种方式:
1.由 Ezio 亲自告知,即代价为 val[i]。
2.由一个与之有关系且已经得到情报的团体以 cost(u,v) 为代价得到情报。

现在 Ezio 想要花费最少的代价让所有团体得到情报,你能帮帮他吗?

输入的第一行表示测试数据组数,满足  

数据范围:每组测试用例满足

输入描述

第一行一个整数t(1 <= t <= 5),表示测试用例组数。

对于每组测试用例:

第一行两个用空格隔开的整数n和m(1 <= n, m <= 100000),分别表示团体个数和关系数量。

接下来一行n个用空格隔开的数,第i个数表示val[i]。

接下来m行,每行三个用空格隔开的整数u,v和cost(u,v)(1 <= u, v <= n, 1 <= val[i], cost(u, v) <= 20000)。

输出描述

对于每组测试用例,你的程序需要输出一行一个整数表示询问的答案。

示例1

输入:

2
5 8
2 8 5 1 10
1 2 5
1 3 9
3 4 5
2 5 6
3 2 2
1 3 8
5 3 4
4 1 8
5 8
7 2 9 10 3
1 2 8
1 3 6
1 4 4
2 5 3
4 5 2
2 4 9
3 5 3
5 4 2

输出:

14
14

原站题解

C++ 解法, 执行用时: 156ms, 内存消耗: 9976KB, 提交时间: 2020-07-28

#include<stdio.h>
#include<algorithm>
using namespace std;
    
struct edge {
    int u, v, w;
    bool operator< (struct edge &A) const {
        return w < A.w;
    }
}E[200000];
    
int p[100002];
int val[100000];
    
int parents(int x) {
    if (x != p[x])
        p[x] = parents(p[x]);
    return p[x];
}
    
int main() {
    int t;
    scanf("%d", &t);
    while (t > 0) {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i++) {
            scanf("%d", &val[i]);
        }
        for (int i = 0; i < m; i++) {
            scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].w);
        }
        for (int i = 0; i < n; i++) {
            E[i + m].u = n + 1;
            E[i + m].v = i + 1;
            E[i + m].w = val[i];
        }
        for (int i = 1; i <= n + 1; i++) {
            p[i] = i;
        }
        sort(E, E + n + m);
        long long sum = 0;
        for (int i = 0, cnt = 0; i < m + n && cnt <= n-1 ; i++) {
            int p_u = parents(E[i].u);
            int p_v = parents(E[i].v);
            if (p_v != p_u) {
                p[p_v] = p_u;
                sum += E[i].w;
                cnt++;
            }
        }
        printf("%lld\n", sum);
        t--;
    }
}

C++ 解法, 执行用时: 162ms, 内存消耗: 3508KB, 提交时间: 2020-10-29

#include<stdio.h>
#include<algorithm>
using namespace std;
   
struct edge {
    int u, v, w;
    bool operator< (struct edge &A) const {
        return w < A.w;
    }
}E[200000];
   
int p[100002];
int val[100000];
   
int parents(int x) {
    if (x != p[x])
        p[x] = parents(p[x]);
    return p[x];
}
   
int main() {
    int t;
    scanf("%d", &t);
    while (t > 0) {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i++) {
            scanf("%d", &val[i]);
        }
        for (int i = 0; i < m; i++) {
            scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].w);
        }
        for (int i = 0; i < n; i++) {
            E[i + m].u = n + 1;
            E[i + m].v = i + 1;
            E[i + m].w = val[i];
        }
        for (int i = 1; i <= n + 1; i++) {
            p[i] = i;
        }
        sort(E, E + n + m);
        long long sum = 0;
        for (int i = 0, cnt = 0; i < m + n && cnt <= n-1 ; i++) {
            int p_u = parents(E[i].u);
            int p_v = parents(E[i].v);
            if (p_v != p_u) {
                p[p_v] = p_u;
                sum += E[i].w;
                cnt++;
            }
        }
        printf("%lld\n", sum);
        t--;
    }
}

上一题