链接:https://ac.nowcoder.com/acm/contest/330/G
来源:牛客网
题目描述
众所周知,Applese 是个很强的选手,它的化学一定很好。
今天他又AK了一套题觉得很无聊,于是想做个毒气炸弹玩。
毒气炸弹需要 k 种不同类型元素构成,Applese一共有 n 瓶含有这些元素的试剂。
已知元素混合遵循 m 条规律,每一条规律都可以用 "x y c" 描述。
表示将第 x 瓶试剂混入第 y 瓶试剂或者把第 y 瓶试剂混入第 x 瓶试剂,需要消耗 c 的脑力。
特别地,除了这 m 条规律外,Applese 可以将任意两瓶相同元素的试剂混合,且不需要消耗脑力。
输入描述:
第一行为三个整数 n, m, k 表示 Applese 拥有的试剂的数量,混合规律的数量和所需的元素种类数。
第二行为 n 个整数 a1,a2,…,ana1,a2,…,an,分别表示每一瓶试剂的元素类型。
接下来m行,每行三个整数 x, y, c,含义如题目描述中所述。不保证 x, y的试剂种类不同。
输出描述:
输出一个正整数表示最小的耗费脑力。特别地,如果无法合成出毒气炸弹,输出 "-1"。
示例1
输入
6 8 2 1 1 1 2 2 2 1 2 1 2 3 2 1 3 3 3 4 6 4 5 1 4 6 3 5 6 2 1 6 2
输出
2
备注:
1≤n,k,m≤1051≤n,k,m≤105
1≤x,y≤n,x≠y1≤x,y≤n,x≠y
1≤c≤109
#include<stdio.h> #include<iostream> #include<algorithm> #include<cstring> #include<math.h> #include<string> #define ll long long #define inf 0x3f3f3f3f using namespace std; int n,m,k; int a[100086]; int par[100086]; struct node { int u; int v; int cost; }; node edge[100086]; bool cmp(node p1,node p2) { return p1.cost<p2.cost; } void init(int n) { for(int i=1;i<=n;i++) par[i]=i; } int find(int x) { if(x==par[x]) return x; else return par[x]=find(par[x]); } void unite(int x,int y) { int xx=find(x); int yy=find(y); if(xx!=yy) par[yy]=xx;//认xx为老大 } bool same(int x,int y) { return find(x)==find(y); } ll Kruskal() { sort(edge+1,edge+m+1,cmp); init(k); ll res=0; int num=1; for(int i=1;i<=m;i++) { node e=edge[i]; if( !same( e.u,e.v ) ) { unite( e.u,e.v ); num++; res+=e.cost; } } if(num==k) return res; else return -1; } int main() { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]);//a的下标是药瓶,内容是元素 int x,y,c; for(int i=1;i<=m;i++) {//将第 x 瓶试剂混入第 y 瓶试剂或者把第 y 瓶试剂混入第 x 瓶试剂,需要消耗 c 的脑力。 scanf("%d%d%d",&x,&y,&c); edge[i].u=a[x];//存的是元素,相同元素的药瓶可以相通 edge[i].v=a[y]; edge[i].cost=c; } printf("%lld\n",Kruskal()); return 0; }