资源here
Kruskal
会对每一条作处理?Kruskal
将会比较耗费时间,所以Kruskal
比较适合处理边比较少的图,也就是所谓的稀疏图。而prim普里姆算法(根据点来挑选边)就相对而言比较适合处理边比较多的图,也就是所谓的稠密图。struct Kruskal{ 点1,点2,路径长 }kru[N*N]; int find(int i){ 是否等于本身?是,返回本身;否 } bool cmp(Kruskal a,Kruskal b){//路径从小到大排,也可以在结构体内重载运算符 return a.z<b.z; } int main(){ 并查集数组的初始化————刚开始谁都不服谁,谁都只服自己 读入 sort(kru+1,kru+1+m,cmp); for(int i=1;i<=m;i++){ 找到线段的一个端点的父节点(?) 找到线段的另一个端点的父节点(?) if(如果两者的父节点相等的话,即我们不希望的环产生了) continue; f[端点1]=端点2; 打不过就加入 } }
给定一个 n 个点 mm 条边的无向图,图中可能存在重边和自环,边权可能为负数。
求最小生成树的树边权重之和,如果最小生成树不存在则输出 impossible
。
给定一张边带权的无向图 G=(V,E),其中 V表示图中点的集合,E表示图中边的集合,n=|V|,m=|E||。
由 V 中的全部 n 个顶点和 E 中 n−1 条边构成的无向连通子图被称为 G的一棵生成树,其中边的权值之和最小的生成树被称为无向图 G 的最小生成树。
第一行包含两个整数 n 和 m。
接下来 mm 行,每行包含三个整数 u,v,w,表示点 u 和点 v 之间存在一条权值为 w 的边。
共一行,若存在最小生成树,则输出一个整数,表示最小生成树的树边权重之和,如果最小生成树不存在则输出 impossible
。
1≤n≤10e5,
1≤m≤2∗10e5,
图中涉及边的边权的绝对值均不超过 10001000。
4 5 1 2 1 1 3 2 1 4 3 2 3 2 3 4 4
6
#include<bits/stdc++.h> #define fir(i,a,b) for(int i=a;i<b;i++) using namespace std; const int N = 1e5+10,M = 2e5+10; struct edge{ int u,v; int cost; bool operator<(const edge& x) { return cost<x.cost; } }krus[M]; int f[N]; int find(int x) { return f[x] == x? x:f[x]=find(f[x]); } int main() { int n,m; cin>>n>>m; fir(i,1,n+1)//并查集初始化 f[i]=i; fir(i,0,m) cin>>krus[i].u>>krus[i].v>>krus[i].cost; sort(krus,krus+m); int total = 0; fir(i,0,m) { int u = krus[i].u,v = krus[i].v; if(find(u)==find(v))//这条边加进来会导致环的出现 continue; total += krus[i].cost; //f[u] = v; 错误写法,这种写法只是将u和f[u]剥离开来,并将f[u]指向v f[find(u)] = find(v);//老大低头认另一帮派的老大才算数 } int com = find(1); bool flag_connected = 1; fir(i,2,n+1) { if(find(i) != com) { flag_connected = 0; break; } } if(flag_connected) cout<<total<<endl; else cout<<"impossible"<<endl; return 0; }