Hướng dẫn giải của Cây khung nhỏ nhất (HEAP)
Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này
Code mẫu của flashmt
var n,m,i,j,x,y,re:longint; a,b,c,d:array[1..15555] of longint; procedure sort(l,r:longint); var i,j,x,y:longint; begin i:=l; j:=r; x:=c[(i+j) shr 1]; repeat while c[i]<x do i:=i+1; while c[j]>x do j:=j-1; if i<=j then begin y:=a[i]; a[i]:=a[j]; a[j]:=y; y:=b[i]; b[i]:=b[j]; b[j]:=y; y:=c[i]; c[i]:=c[j]; c[j]:=y; i:=i+1; j:=j-1; end; until i>j; if i<r then sort(i,r); if l<j then sort(l,j); end; function find(x:longint):longint; begin if x<>d[x] then d[x]:=find(d[x]); exit(d[x]); end; begin read(n,m); for i:=1 to n do d[i]:=i; for i:=1 to m do read(a[i],b[i],c[i]); sort(1,m); for i:=1 to m do begin x:=find(a[i]); y:=find(b[i]); if x<>y then begin d[y]:=x; dec(n); re:=re+c[i]; if n=1 then begin writeln(re); halt; end; end; end; end.
Code mẫu của happyboy99x
#include <cstdio> #include <algorithm> #include <vector> using namespace std; typedef pair<int, int> ii; typedef pair<int, ii> i3; #define fi first #define se second int n, m; vector<i3> g; int r[10005]; int getr( int u ) { return u == r[u] ? u : r[u] = getr(r[u]); } int main() { scanf( "%d%d", &n, &m ); for( int i = 0; i < m; ++i ) { int u, v, l; scanf( "%d%d%d", &u, &v, &l ); g.push_back(i3(l, ii(--u, --v))); } sort(g.begin(), g.end()); for( int i = 0; i < n; ++i ) r[i] = i; int c = 0, res = 0; for( typeof(g.begin()) it = g.begin(), _e = g.end(); c != n-1 && it != _e; ++it ) { int u = it->se.fi, v = it->se.se, l = it->fi; if (getr(u) != getr(v)) { res += l; ++c; r[r[u]] = r[v]; } } printf( "%d\n", res ); return 0; }
Code mẫu của ladpro98
//http://vn.spoj.com/problems/QBMST/ #include <bits/stdc++.h> #define ii pair<int, int> #define iii pair<int, ii> #define X first #define Y second const int N = 10050; const int M = 15050; using namespace std; int n, m; int lab[N]; iii e[M]; int root(int u) { if (lab[u] <= 0) return u; return lab[u] = root(lab[u]); } void unite(int u, int v) { if (lab[u] < lab[v]) lab[v] = u; else { if (lab[u] == lab[v]) lab[v]--; lab[u] = v; } } int main() { scanf("%d %d", &n, &m); int i, x, y, cnt = 0, res = 0; for(i = 1; i <= m; i++) scanf("%d %d %d", &e[i].Y.X, &e[i].Y.Y, &e[i].X); sort(e + 1, e + 1 + m); for(i = 1; i <= m; i++) { x = root(e[i].Y.X); y = root(e[i].Y.Y); if (x != y) { unite(x, y); res += e[i].X; cnt++; } if (cnt == n - 1) break; } printf("%d", res); return 0; }
Code mẫu của RR
var u,v,res,i,n,m:longint; lab,eu,ev,ec:array[1..15111] of longint; procedure swap(var a,b:longint); var tmp:longint; begin tmp:=a; a:=b; b:=tmp; end; procedure sort(l,r:longint); var i,j,mid:longint; begin i:=l; j:=r; mid:=ec[l+random(r-l+1)]; repeat while ec[i]<mid do inc(i); while ec[j]>mid do dec(j); if i<=j then begin swap(eu[i],eu[j]); swap(ev[i],ev[j]); swap(ec[i],ec[j]); inc(i); dec(j); end; until i>j; if i<r then sort(i,r); if l<j then sort(l,j); end; procedure union(r1,r2:longint); var x:longint; begin x:=lab[r1]+lab[r2]; if lab[r1]<lab[r2] then begin lab[r1]:=x; lab[r2]:=r1; end else begin lab[r2]:=x; lab[r1]:=r2; end; end; function getRoot(u:longint):longint; begin if lab[u]<0 then exit(u); lab[u]:=getRoot(lab[u]); exit(lab[u]); end; begin read(n,m); for i:=1 to m do read(eu[i],ev[i],ec[i]); sort(1,m); for i:=1 to n do lab[i]:=-1; for i:=1 to m do begin u:=getRoot(eu[i]); v:=getRoot(ev[i]); if u<>v then begin union(u,v); inc(res,ec[i]); end; end; writeln(res); end.
Code mẫu của hieult
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> //#include <conio.h> using namespace std; #define MAX(a,b) ((a>b)?a:b) #define CLEAR(A,N) (memset(A,0,(N)*sizeof(A[0]))) const int maxEdgeSize = 200005; typedef struct{ int x,y,cost; }graph; graph v[maxEdgeSize]; int ar[maxEdgeSize]; int findSet(int i){ while(ar[i]!=i) i = ar[i]; return i; } void makeUnion(int a,int p1,int b, int p2){ int x = MAX(p1,p2); ar[a] = x; ar[b] = x; ar[p1] = x; ar[p2] = x; } int adjustUsingUnionFind(int a,int b) { if(ar[a] == -1) ar[a] = a; if(ar[b] == -1) ar[b] = b; int p1 = findSet(a); int p2 = findSet(b); if(p1!=p2){ makeUnion(a,p1,b,p2); return 1; } else return 0; } bool operator < (graph a, graph b) { return a.cost < b.cost; } int main() { //freopen("QBMST.in","r",stdin); int m,n,i,minimumCost; scanf("%d %d",&m,&n); for(int i = 0;i<n;i++) scanf("%d %d %d",&v[i].x,&v[i].y,&v[i].cost); sort(v,v+n); for(int i = 0;i<=m;i++) ar[i] = -1; minimumCost = 0; for(int i = 0;i<n;i++) { if(adjustUsingUnionFind(v[i].x,v[i].y)==1) { minimumCost+= v[i].cost; //printf("%d\n",v[i].cost); } } printf("%d",minimumCost); //getch(); }
Code mẫu của ll931110
Program QBMST; Const input = ''; output = ''; maxn = 10000; maxm = 15000; maxc = 1000000000; Type arrn = array[0..maxn + 1] of longint; arrm = array[1..maxm + 1] of longint; arr = array[0..2 * maxm + 1] of longint; check = array[1..maxn] of boolean; Var x,y,c: arrm; h,adj,adjcost: arr; d,trace,heap,pos: arrn; n,m,nHeap: longint; free: check; Procedure LoadGraph; Var f: text; i: longint; Begin Assign(f, input); Reset(f); Fillchar(h, sizeof(h), 0); Readln(f, n, m); For i:= 1 to m do Begin Readln(f, x[i], y[i], c[i]); inc(h[x[i]]); inc(h[y[i]]); End; Close(f); For i:= 2 to n do h[i]:= h[i] + h[i - 1]; For i:= 1 to m do Begin adj[h[x[i]]]:= y[i]; adjcost[h[x[i]]]:= c[i]; dec(h[x[i]]); adj[h[y[i]]]:= x[i]; adjcost[h[y[i]]]:= c[i]; dec(h[y[i]]); End; h[n + 1]:= 2 * m; End; Procedure init; Var i: integer; Begin d[1]:= 0; For i:= 2 to n do d[i]:= maxc; Fillchar(pos, sizeof(pos), 0); Fillchar(free, sizeof(free), true); Fillchar(trace, sizeof(trace), 0); nHeap:= 0; End; Procedure Update(v: longint); Var parent,child: longint; Begin child:= pos[v]; If child = 0 then Begin inc(nHeap); child:= nHeap; End; parent:= child div 2; While (parent > 0) and (d[heap[parent]] > d[v]) do Begin heap[child]:= heap[parent]; pos[heap[child]]:= child; child:= parent; parent:= child div 2; End; heap[child]:= v; pos[v]:= child; End; Function pop: longint; Var r,c,v: longint; Begin pop:= heap[1]; v:= heap[nHeap]; dec(nHeap); r:= 1; While r * 2 <= nHeap do Begin c:= r * 2; If (c < nHeap) and (d[heap[c]] > d[heap[c + 1]]) then inc(c); If d[v] <= d[heap[c]] then break; heap[r]:= heap[c]; pos[heap[r]]:= r; r:= c; End; heap[r]:= v; pos[v]:= r; End; Procedure Prim; Var i,u,v,iv: longint; Begin Update(1); Repeat u:= pop; free[u]:= false; For iv:= h[u] + 1 to h[u + 1] do Begin v:= adj[iv]; If free[v] and (d[v] > adjcost[iv]) then Begin d[v]:= adjcost[iv]; trace[v]:= u; update(v); End; End; Until nHeap = 0; End; Procedure printresult; Var f: text; u,v,iv,res: longint; Begin Assign(f, output); Rewrite(f); res:= 0; For u:= 2 to n do For iv:= h[u] + 1 to h[u + 1] do Begin v:= adj[iv]; If v = trace[u] then Begin res:= res + adjcost[iv]; break; End; End; Writeln(f, res); Close(f); End; Begin LoadGraph; init; Prim; printresult; End.
Code mẫu của skyvn97
#include<cstdio> #include<algorithm> #define MAX 15151 using namespace std; struct edge { int u,v,w; bool operator < (const edge &x) const { if (w<x.w) return (true); if (w>x.w) return (false); return (u+v<x.u+x.v); } }; int up[MAX]; edge e[MAX]; int m,n; void init(void) { scanf("%d",&n); scanf("%d",&m); int i; for (i=1;i<=m;i=i+1) { scanf("%d",&e[i].u); scanf("%d",&e[i].v); scanf("%d",&e[i].w); } for (i=1;i<=n;i=i+1) up[i]=-1; sort(&e[1],&e[m+1]); } int find(int x) { if (up[x]<0) return (x); up[x]=find(up[x]); return (up[x]); } void join(int a,int b) { int x=find(a); int y=find(b); if (x==y) return; up[y]=x; } void kruskal(void) { int i,c,s; c=0;s=0; for (i=1;i<=m;i=i+1) { if (find(e[i].u)!=find(e[i].v)) { join(e[i].u,e[i].v); c=c+1; s=s+e[i].w; if (c==n-1) { printf("%d",s); return; } } } } int main(void) { init(); kruskal(); return 0; }
Code mẫu của khuc_tuan
#include <stdio.h> #include <iostream> using namespace std; int n, m, f[15000]; pair<int, pair<int,int> > a[16600]; int getroot(int i) { return (f[i]<0) ? i : getroot(f[i]); } void merge(int i, int j) { i = getroot(i); j = getroot(j); if(f[i]>f[j]) swap(i,j); f[i] += f[j]; f[j] = i; } int main() { scanf("%d%d", &n, &m); for(int i=0;i<m;++i) scanf("%d%d%d", &a[i].second.first, &a[i].second.second, &a[i].first); sort( a, a+m); int res = 0; memset( f, -1, sizeof(f)); for(int i=0;i<m;++i) { int u = a[i].second.first; int v = a[i].second.second; if(getroot(u)!=getroot(v)) { merge(u,v); res += a[i].first; } } printf("%d\n", res); return 0; }
Bình luận