//kruskal算法,用优先队列解法,尽量用第一个模版
例题:挖沟:https://ac.nowcoder.com/acm/problem/17509
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stdlib.h>
typedef long long ll;
using namespace std;
const int N = 500010;
struct node
{
int u,v,w;
friend bool operator < (const node &x,const node &y)
{
return x.w > y.w;
}
};
int n,m,fa[N],sum;
priority_queue<node> q;
int find(int n)
{
if(fa[n] == n) return n;
return fa[n] = find(fa[n]);
}
void un(int a,int b)
{
fa[find(a)] = fa[find(b)];
}
void kruskal()
{
for(int i = 1;i <= n;i++)
{
fa[i] = i;
}
while(!q.empty())
{
int u = q.top().u;
int v = q.top().v;
int w = q.top().w;
q.pop();
if(find(u) != find(v))
{
un(u,v);
sum += w;
}
}
}
int main()
{
cin >> n >> m;
sum=0;
for(int i = 1;i <= m;i++) //m为边数,n为点的个数
{
int a,b,v;
cin >> a >> b >> v;
q.push({a,b,v}); //q.push这里一定要加{ },这里比较容易出错
}
kruskal();
cout << sum << endl;
return 0;
}
//第二个模版
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stdlib.h>
typedef long long ll;
using namespace std;
struct edge
{
ll u,v,w;
}e[200010];
bool cmp(edge &a,edge &b)
{
return a.w<b.w;
}
ll f[200005],n,m,ans,cnt;
ll find(ll x)
{
if(f[x]!=x) f[x]=find(f[x]);
return f[x];
}
void kruskal()
{
sort(e,e+m,cmp);
for(int i=0;i<m;i++)
{
ll u=e[i].u;
ll v=e[i].v;
ll w=e[i].w;
ll fu=find(u), fv=find(v);
if(fu==fv) continue; //如果两者在一个连通图里面,continue
ans+=w;
f[fv]=fu; cnt++;
if(cnt==n-1) break; //最小生成树只有n-1条边
}
}
int main()
{
cin >> n >> m;
for(int i=1;i<=n;i++)
{
f[i]=i;
}
//每个点都自成一个连通量
for(int i=0;i<m;i++)
{
cin >> e[i].u >> e[i].v >> e[i].w; //输入两个端点和边的权值
}
kruskal();
if(cnt!=n-1)
{
printf("orz");
}
printf("%lld",ans);
return 0;
}