题目链接
题目思路
要先用dfs把从1能到的点筛选出来, 加边的时候不要else if 因为当H[a] == H[b]的时候, 是双向边
然后用Kruskal算法求解
代码实现
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10, M = 3e6 + 10;
int e[M], ne[M], h[N], idx;
int p[N], H[N];
int n, m; 
LL cnt, res;
bool vis[N];
struct Edge
{
    int u, v, w;
    bool operator < (const Edge &W)const
    {
        if (H[v] != H[W.v]) return H[v] > H[W.v];
        return w < W.w;
    }
}edge[M];
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
int find(int a)
{
    if (p[a] != a) p[a] = find(p[a]);
    return p[a];
}
void dfs(int nu)
{
    vis[nu] = 1;
    cnt ++;
    for (int i = h[nu]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (vis[j]) continue;
        dfs(j);
    }
}
void Kruskal()
{
    sort(edge, edge + m);
    for (int i = 1; i <= n; i ++ ) p[i] = i;
    for (int i = 0; i < m; i ++ )
    {
        auto e = edge[i];
        if (!vis[e.u] || !vis[e.v]) continue;
        int pu = find(e.u), pv = find(e.v);
        if (pu != pv)
        {
            p[pu] = pv;
            res += (LL)e.w;
        }
    }
}
int main()
{
    cin.tie(0); cout.tie(0);
    ios::sync_with_stdio(false);
    memset(h, -1, sizeof h);
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ ) cin >> H[i];
    for (int i = 0; i < m; i ++ )
    {
        int a, b, c;
        cin >> a >> b >> c;
        if (H[a] >= H[b]) edge[i] = {a, b, c}, add(a, b);
        if (H[a] <= H[b]) edge[i] = {b, a, c}, add(b, a);
    }
    dfs(1);
    Kruskal();
    cout << cnt << ' ' << res << endl;
    return 0;
}
 京公网安备 11010502036488号
京公网安备 11010502036488号