У задачі необхідно знайти вагу мінімального остовного дерева за допомогою алгоритму Крускала.
Приклад Граф, наведений у прикладі, має такий вигляд:
Вправа 1
Знайдіть мінімальний остов і його вагу для наступного графа.
Вправа 2
Знайдіть мінімальний остов і його вагу для наступного графа.
Реалізація алгоритму
Оголосимо структуру для ребра графа (пара вершин і вага ребра). Оголосимо вектор ребер .
struct Edge
{
int u, v, dist;
};
vector<Edge> e;Оголосимо масив , який буде використовуватися в системі непересічних множин.
vector<int> parent;Функція Repr знаходить представника множини, в якій знаходиться вершина .
int Repr(int n)
{
while (n != parent[n]) n = parent[n];
return n;
}Функція Union об'єднує множини, що містять елементи і .
int Union(int x, int y)
{
x = Repr(x); y = Repr(y);
if (x == y) return 0;
parent[y] = x;
return 1;
}Функція lt є компаратором для сортування ребер.
int lt(Edge a, Edge b)
{
return (a.dist < b.dist);
}Основна частина програми. Ініціалізуємо масив .
scanf("%d %d",&n,&m);
parent.resize(n + 1);
for (i = 1; i <= n; i++) parent[i] = i;Читаємо ребра графа.
e.resize(m);
for (i = 0; i < m; i++)
scanf("%d %d %d", &e[i].u, &e[i].v, &e[i].dist);Сортуємо ребра графа за зростанням ваг.
sort(e.begin(), e.end(), lt);Запускаємо алгоритм Крускала для побудови мінімального остовного дерева.
res = 0;
for(i = 0; i < m; i++)
if (Union(e[i].u,e[i].v)) res += e[i].dist;Виводимо вагу мінімального остова.
printf("%d\n",res);Реалізація алгоритму — евристика
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
struct Edge
{
int u, v, dist;
};
vector<Edge> e;
vector<int> parent, depth;
int i, n, m, res;
int Repr(int n)
{
if (n == parent[n]) return n;
return parent[n] = Repr(parent[n]);
}
int Union(int x, int y)
{
x = Repr(x); y = Repr(y);
if (x == y) return 0;
if (depth[x] < depth[y]) swap(x, y);
parent[y] = x;
if (depth[x] == depth[y]) depth[x]++;
return 1;
}
int lt(Edge a, Edge b)
{
return a.dist < b.dist;
}
int main(void)
{
scanf("%d %d", &n, &m);
parent.resize(n + 1);
depth.resize(n + 1);
for (i = 1; i <= n; i++)
{
parent[i] = i;
depth[i] = 0;
}
e.resize(m);
for (i = 0; i < m; i++)
scanf("%d %d %d", &e[i].u, &e[i].v, &e[i].dist);
sort(e.begin(), e.end(), lt);
res = 0;
for (i = 0; i < m; i++)
if (Union(e[i].u, e[i].v)) res += e[i].dist;
printf("%d\n", res);
return 0;
}Реалізація алгоритму — Прим
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#define MAX 101
#define INF 0x3F3F3F3F
using namespace std;
int i, n, m, a, b, c, res;
vector<vector<pair<int, int> > > g; // (to, dist)
int used[MAX], dist[MAX];
int Prim(int start)
{
memset(dist, 0x3F, sizeof(dist));
memset(used, 0, sizeof(used));
int cur = start, res = 0;
dist[cur] = 0;
used[cur] = 1;
for (int i = 1; i < n; i++)
{
for (auto e : g[cur]) // cur -> to
{
int to = e.first;
int d = e.second;
if (!used[to] && (d < dist[to]))
dist[to] = d;
}
int min = INF;
for (int j = 1; j <= n; j++)
if (!used[j] && (dist[j] < min))
{
min = dist[j];
cur = j;
}
used[cur] = 1;
res += dist[cur];
}
return res;
}
int main(void)
{
scanf("%d %d", &n, &m);
g.resize(n + 1);
for (i = 0; i < m; i++)
{
scanf("%d %d %d", &a, &b, &c);
g[a].push_back({ b, c });
g[b].push_back({ a, c });
}
res = Prim(1);
printf("%d\n", res);
return 0;
}Java реалізація
import java.util.*;
class Edge
{
int u, v, dist;
Edge (int u, int v, int dist)
{
this.u = u;
this.v = v;
this.dist = dist;
}
};
public class Main
{
static int mas[];
static int size[];
static int Repr(int n)
{
if (n == mas[n]) return n;
return mas[n] = Repr(mas[n]);
}
static int Union(int x, int y)
{
x = Repr(x); y = Repr(y);
if(x == y) return 0;
if (size[x] < size[y])
{
int temp = x; x = y; y = temp;
}
mas[y] = x;
size[x] += size[y];
return 1;
}
public static class MyFun implements Comparator<Edge>
{
public int compare(Edge a, Edge b)
{
return a.dist - b.dist;
}
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
int n = con.nextInt();
int m = con.nextInt();
mas = new int[n+1];
size = new int[n+1];
for(int i = 1; i <= n; i++)
{
mas[i] = i;
size[i] = 1;
}
Vector<Edge> v = new Vector<Edge>();
for(int i = 0; i < m; i++)
{
int x = con.nextInt();
int y = con.nextInt();
int dist = con.nextInt();
v.add(new Edge(x, y, dist));
}
Collections.sort(v, new MyFun());
int res = 0;
for(int i = 0; i < m; i++)
if (Union(v.get(i).u, v.get(i).v) == 1) res += v.get(i).dist;
System.out.println(res);
con.close();
}
}