最小生成树 Kruskal Prim 模板
并查集模板:
朴素版
const int N = 1e5+5;
int p[N];
void init(int n){
for(int i=0;i<=n;i++)
p[i] = i;
}
int find(int x){
return x==p[x]? x:p[x] = find(p[x]);
}
void merge(int x,int y){
p[find(x)] = find(y);
}
Kruskal:
const int N = 5e6+5;
int n,m,f[N];
int ans;
struct rec{int x,y,z;}edge[N];
bool operator < (rec a,rec b){return a.z < b.z;}
//并查集
int find(int x){
return x == p[x]? x:p[x]=find(p[x]);
}
int main(){
cin >> n >> m;
for(int i = 1;i <= m;i++)scanf("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].z);
//按边权排序
sort(edge + 1 , edge + 1 + m);
//初始化
for(int i = 0;i <= n;i++)p[i] = i;
//求最小生成树
for(int i=1;i <= n; i++){
int x = find(edge[i].x);
int y = find(edge[i].y);
if(x == y) continue;
p[x] = y;
ans += edge[i].z;
}
cout << ans << endl;
}
Prim:
Prim主要用于稠密图
const int N = 1e5+5;
int n,m,a[N][N],d[N];
int ans;
bool v[N];
void prim(){
memset(d, INF, sizeof d);
memset(v, 0 ,sizeof v);
d[1] = 0;
for(int i = 1;i < n; i++){
int x = 0;
for(int j = 1;j <= n;j++)
if(!v[j] && (x == 0|| d[j] < d[x])) x = j;
v[x] = 1;
for(int y = 1;y <= n;y++)
if(!v[y]) d[y] = min(d[y], a[x][y]) ;
}
}
int main(){
cin>> n>> m;
memset(a, 0x3f, sizeof a);
for(int i = 1;i <= n;i++)a[i][i] = 0;
for(int i = 1;i <= m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
a[y][x] = a[x][y] = min(a[x][y], z);
}
prim();
for(int i = 2;i <= n;i++)ans+=d[i];
cout << ans << endl;
}