挖坑(kruskal/prim)

对于prim算法
我们要更新一个点到一个已经在在树里的点的最小距离,作为答案,最开始要将起点加入优先队列,并且最开始要把d数组初始化为最大值
对于kruskal算法
我们需要用到并查集,对所有的边的边权进行排序,如果边的两个不在一个集合,就可以连接两点并让答案加上边权,如果两个点在统一个集合则不能连接,不然会成环,个人认为kruskal算法更简单
/*#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
const int N=1e5+5;
struct node{
int id,dis;
};
int d[N];
vector<node>v[N];
bool operator<(node n1,node n2){
return n1.dis>n2.dis;
}
int n,m;
int vis[N];
long long ans=0;
bool prim(){
int cnt=0;
priority_queue<node>q;
memset(d,0x3f,sizeof(d));
q.push({1,0});
d[1]=0;
while(!q.empty()){
int u=q.top().id;
q.pop();
if(vis[u])continue;
vis[u]=1;
ans+=d[u];
cnt++;
for(int i=0;i<v[u].size();i++){
//if(vis[v[u][i].id])continue;
if(d[v[u][i].id]>v[u][i].dis){
d[v[u][i].id]=v[u][i].dis;
q.push({v[u][i].id,d[v[u][i].id]});
}
}
}
return cnt==n;
}
int main(){
cin>>n>>m;
while(m--){
int a,b,x;
cin>>a>>b>>x;
v[a].push_back({b,x});
v[b].push_back({a,x});
}
if(prim())cout<<ans;
else cout<<"orz";
return 0;
}*/
//kruskal
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int N=5*1e5+5;
int n,m;
struct edge{
int x,y,z;//起点,终点,边权
}e[N];
int f[N];
void init(){
for(int i=1;i<=n;i++)f[i]=i;
}
int find(int x){
return x==f[x]?x:f[x]=find(f[x]);
}
void unite(int x,int y){
int rootx=find(x);
int rooty=find(y);
if(rootx!=rooty)f[rootx]=rooty;
}
bool cmp(edge e1,edge e2){
return e1.z<e2.z;
}
signed main(){
cin>>n>>m;
init();
for(int i=1;i<=m;i++){
cin>>e[i].x>>e[i].y>>e[i].z;
}
sort(e+1,e+1+m,cmp);
int ans=0;
int cnt=0;
for(int i=1;i<=m;i++){
int rootx=find(e[i].x);
int rooty=find(e[i].y);
if(rootx==rooty)continue;
else{
ans+=e[i].z;
cnt++;
unite(e[i].x,e[i].y);
if(cnt==n-1)break;
}
}
if(cnt==n-1)cout<<ans;
return 0;
}

浙公网安备 33010602011771号