kruskal算法 前向星+并查集 需排序(加边,还有一种加点的prim算法,不惯用,就不更了
排序后每次找权值最小的两节点组成的边,加入树,通过并查集确定公共祖先,若某边加入会出现环,跳过,直至所有点都加入树,该树即为最小生成树
板子
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<set> #include<string> using namespace std; const int INF=0x3f3f3f3f; typedef pair<int, int> pr; typedef long long ll; #define fi first #define se second #define me(x) memset(x, -1, sizeof(x)) #define mem(x) memset(x, 0, sizeof(x)) #define MAXN 500000+5 #define NIL -1 struct node { int u, v, w; }edge[MAXN]; bool cmp(node a, node b) { if(a.w==b.w && a.u==b.u) return a.v<b.v; if(a.w==b.w) return a.u<b.u; return a.w<b.w; } int p[MAXN];//存祖先 记录每个点的前导点 int ans, n, m; int Find(int x) //查找根节点 { int r=x; while(p[r]!=r) //根节点的上级节点为本身 r=p[r]; //r为根节点 int i=x, j; while(p[i]!=r)//until p[p[i]]==r 路径压缩 不断更新i的上级节点为根节点 { j=p[i]; p[i]=r; //r为根 i=j; } // 1 --> 3 --> 4 --> 5 return r; } int mix() //合并 联通 { for(int i=0; i<m; i++) { int fx=Find(edge[i].u), fy=Find(edge[i].v); if(fx!=fy) ans+=edge[i].w, p[fx]=fy; } } int main() { int i, j, k; while(cin>>n>>m) { ans=0; for(i=1; i<=n; i++) p[i]=i; //初始化每个点的父节点为本身 for(i=0; i<m; i++) cin>>edge[i].u>>edge[i].v>>edge[i].w; sort(edge, edge+m, cmp); mix(); cout<<ans<<endl; } }
模板题
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> #include<string> #include<cstring> #include<map> #include<stack> #include<set> #include<queue> using namespace std; typedef long long ll; #define me(x) memset(x, -1, sizeof(x)) #define mem(x) memset(x, 0, sizeof(x)) const int MOD = 1e18; const int N = 2e6 + 5; int a[1005][1005], vis[1005][1005]; struct node { int u, v, d; }e[N]; int p[N]; int n, m, id, ans; void ini() { id=0; mem(vis); } void add(int u, int v, int d) { e[id].u = u; e[id].v = v; e[id].d = d; id++; } bool cmp(node a, node b) { if(a.d==b.d && a.u==b.u) return a.v<b.v; else if(a.d==b.d) return a.u<b.u; else return a.d<b.d; } int Find(int x) { int r=x; while(r!=p[r]) { r=p[r]; } int i=x, t; while(r!=p[i]) { t=p[i]; p[i]=r; i=t; } return r; } void join() { for(int i=0; i<id; i++) { int x=Find(e[i].u), y=Find(e[i].v); if(x!=y) { p[x]=y; ans+=e[i].d; } } } int main() { int i, j, k; int t; scanf("%d", &n); int u, v, d; ini(); for(i=1; i<=n; i++) { p[i]=i; for(j=1; j<=n; j++) scanf("%d", &a[i][j]); } scanf("%d", &m); for(i=0; i<m; i++) scanf("%d%d", &u, &v), a[u][v]=a[v][u]=0; for(i=1; i<=n; i++) for(j=1; j<=n; j++) if(i!=j) add(i,j,a[i][j]); sort(e, e+id, cmp); ans=0; join(); printf("%d ", ans); }