F.Make It Connected
You are given an undirected graph consisting of n vertices. A number is written on each vertex; the number on vertex i is ai. Initially there are no edges in the graph.
You may add some edges to this graph, but you have to pay for them. The cost of adding an edge between vertices x and y is ax+ay coins. There are also m special offers, each of them is denoted by three numbers x, y and w, and means that you can add an edge connecting vertices x and y and pay w coins for it. You don’t have to use special offers: if there is a pair of vertices x and y that has a special offer associated with it, you still may connect these two vertices paying ax+ay coins for it.
What is the minimum number of coins you have to spend to make the graph connected? Recall that a graph is connected if it’s possible to get from any vertex to any other vertex using only the edges belonging to this graph.
Input
The first line contains two integers n and m (1≤n≤2⋅105, 0≤m≤2⋅105) — the number of vertices in the graph and the number of special offers, respectively.
The second line contains n integers a1,a2,…,an (1≤ai≤1012) — the numbers written on the vertices.
Then m lines follow, each containing three integers x, y and w (1≤x,y≤n, 1≤w≤1012, x≠y) denoting a special offer: you may add an edge connecting vertex x and vertex y, and this edge will cost w coins.
Output
Print one integer — the minimum number of coins you have to pay to make the graph connected.
Examples
Input
3 2
1 3 3
2 3 5
2 1 1
Output
5
Input
4 0
1 3 3 7
Output
16
Input
5 4
1 2 3 4 5
1 2 8
1 3 10
1 4 7
1 5 15
Output
18
思路:
如果不考虑m条额外的边,贪心一下发现每个点连接点权最小的点花费最小,
然后考虑用m条额外的边替换,把之前连接最小的的边和m条额外边放在一起跑kruskal就行了。
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=2e5+5;
struct Node{
int a,b,c;
bool operator<(const Node a){
return c<a.c;
}
}e[maxm<<1];
int pre[maxm];
int p[maxm];
int n,m;
void init(){
for(int i=0;i<maxm;i++){
pre[i]=i;
}
}
int ffind(int x){
return pre[x]==x?x:pre[x]=ffind(pre[x]);
}
signed main(){
init();
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>p[i];
}
int mi=1;
for(int i=1;i<=n;i++){//找最小
if(p[mi]>p[i]){
mi=i;
}
}
int num=0;
for(int i=1;i<=n;i++){
if(mi==i)continue;
e[++num]={i,mi,p[i]+p[mi]};
}
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
e[++num]={a,b,c};
}
sort(e+1,e+1+num);
int cnt=0;
int ans=0;
for(int i=1;i<=num;i++){
int x=ffind(e[i].a);
int y=ffind(e[i].b);
if(x!=y){
pre[x]=y;
ans+=e[i].c;
cnt++;
if(cnt==n-1)break;
}
}
cout<<ans<<endl;
return 0;
}