题目链接:https://ac.nowcoder.com/acm/contest/330/G

       题意有点绕,但读懂以后其实就是一个最小生成树。让每个试剂作为结点,然后建边就好了,要严格要求xx要等于k,xx大于k也是不行的...


AC代码:

#include <bits/stdc++.h>
#define maxn 100005
#define ll long long
using namespace std;
struct Node{
  int x,y;
  ll w;
  bool operator < (const Node &a)const{
    return a.w > w;
  }
}Edge[maxn];
int a[maxn],pre[maxn];
int n,m,k,num;

void init(){
  for(int i=0;i<=k;i++){
    pre[i] = i;
  }
  num = 0;
}

void add(int u,int v,ll w){
  Edge[num].x = u;
  Edge[num].y = v;
  Edge[num++].w = w;
}

int Find(int x){
  if(x != pre[x]){
    pre[x] = Find(pre[x]);
  }
  return pre[x];
}

ll Kruskal(){
  ll xx = 1;
  ll sum = 0;
  sort(Edge, Edge + num);
  for(int i=0;i<num;i++){
    int fx = Find(Edge[i].x);
    int fy = Find(Edge[i].y);
    if(fx != fy){
      pre[fy] = fx;
      xx ++;
      sum += Edge[i].w;
    }
  }
  return xx == k ? sum : -1;
}

int main()
{
  scanf("%d%d%d",&n,&m,&k);
  init();
  for(int i=1;i<=n;i++) scanf("%d",&a[i]);
  for(int i=0;i<m;i++){
    int u, v;
    ll w;
    scanf("%d%d%lld",&u, &v, &w);
    add(a[u], a[v], w);
  }
  ll ans = Kruskal();
  printf("%lld\n", ans);
  return 0;
}