果 断 k r u 生 成 树 , 但 是 不 能 把 所 有 边 加 进 去 果断kru生成树,但是不能把所有边加进去 果断kru生成树,但是不能把所有边加进去

感 性 证 明 \color{Red}感性证明 感性证明

如果使用第一条规则,一定是每个点和点权最小的点连接

所 以 只 需 要 把 每 个 点 和 最 小 点 的 边 加 入 数 组 , 跑 k r u 就 行 了 所以只需要把每个点和最小点的边加入数组,跑kru就行了 所以只需要把每个点和最小点的边加入数组,跑kru就行了

为 什 么 ? 假 如 不 和 最 小 点 权 点 相 连 , 就 一 定 使 用 第 二 条 规 则 , 第 二 条 规 则 加 的 边 在 k r u 生 成 树 已 经 考 虑 了 为什么?假如不和最小点权点相连,就一定使用第二条规则,第二条规则加的边在kru生成树已经考虑了 为什么?假如不和最小点权点相连,就一定使用第二条规则,第二条规则加的边在kru生成树已经考虑了

否 则 , 一 定 和 最 小 点 权 点 相 连 。 否则,一定和最小点权点相连。 否则,一定和最小点权点相连。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
struct S{
ll u,v,w;
bool operator < (const S &tmp ) const{
return this->w<tmp.w;
}
}d[maxn<<1];
typedef pair<ll,ll>p;
p a[maxn];
ll pre[maxn],n,m,top;
ll find(ll x){
return x==pre[x]?pre[x]:pre[x]=find(pre[x]);
}
void join(ll q,ll w)
{
pre[find(q)]=find(w);
}
ll kur()
{
sort(d+1,d+1+top);
ll ans=0,j=1;
for(int i=1;i<n;i++)
{
for(;j<=top;j++)
{
ll u=d[j].u,v=d[j].v,w=d[j].w;
if(find(u)==find(v)) continue;
join(u,v), ans+=w;
break;
}
}
return ans;
}
int main()
{
cin >> n >> m;
for(int i=1;i<=n;i++) pre[i]=i;
for(int i=1;i<=n;i++)
{
cin >> a[i].first;
a[i].second=i;
}
sort(a+1,a+1+n);
for(int i=2;i<=n;i++)
d[++top].u=a[1].second,d[top].v=a[i].second,d[top].w=a[1].first+a[i].first;
for(int i=1;i<=m;i++)
{
++top;
cin >> d[top].u >> d[top].v >> d[top].w;
}
cout<<kur();
}