1. Preguntas
Dé un ejemplo, dibuje el proceso de usar el algoritmo Prim para construir el árbol de expansión mínimo y escriba el algoritmo de acuerdo con la plantilla de informe experimental.
Dé un ejemplo, dibuje el proceso de usar el algoritmo de Kruskal para construir el árbol de expansión mínimo y escriba el algoritmo de acuerdo con la plantilla de informe experimental.
2. Resolver
en un gráfico no dirigido dado G = (V, E), (u, v) representa la arista que conecta el vértice u y el vértice v, w (u, v) representa el peso de esta arista, si hay T Si es un subconjunto de E y un gráfico acíclico, de modo que w (T) es el más pequeño, entonces este T es el árbol de expansión mínimo de G.
Algoritmo Prim:
Suponga que el conjunto de puntos en el árbol de expansión mínimo es U. Al principio, el árbol de expansión mínimo está vacío, por lo que U está vacío.
Algoritmo de Kruskal:
Sea T el conjunto de aristas del árbol de expansión mínimo y que el árbol de expansión mínimo esté vacío al principio, por lo que T está vacío.
3. Diseño
Principal:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<map>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<set>
#include<cctype>
#include<string>
#include<stdexcept>
#include<fstream>
#include<sstream>
#include<sstream>
#define mem(a,b) memset(a,b,sizeof(a))
#define debug() puts("what the fuck!")
#define dedebug() puts("what the fuck!!!")
#define ll long long
#define ull unsigned long long
#define speed {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); };
using namespace std;
const double PI = acos(-1.0);
const int maxn = 2e5 + 10;
const int N = 2e3 + 10;
const ll INF = 1e18;
const ll mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const double esp_0 = 1e-6;
const double gold = (1 + sqrt(5)) / 2;
inline int rd() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch>'9') {
if (ch == '-')f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
ll quick(ll a, ll b) {
ll ans = 1;
while (b) {
if (b % 2) {
ans = ans * a % mod;
}
b >>= 1;
a = a * a % mod;
}
return ans % mod;
}
ll gcd(ll x, ll y) {
return y ? gcd(y, x % y) : x;
}
int n, m;
int g[110][110];
int dis[110];
int vis[110];
int prim() {
memset(vis, 0, sizeof vis);//标记数组
memset(dis, inf, sizeof dis);//最小生成树节点间距离
dis[1] = 0;
for (int i = 1; i < m; ++i) {
int pos = 0;
for (int j = 1; j <= m; ++j) {
if (!vis[j] && (pos == 0 || dis[j] < dis[pos]))pos = j;
}
vis[pos] = 1;
for (int j = 1; j <= m; ++j) {
if (!vis[j])dis[j] = min(dis[j], g[pos][j]);
}
}
int ans = 0;
for (int i = 1; i <= m; ++i) {
if (dis[i] == inf)return -1;//如果有一个点的dis值为inf,说明该点被孤立,原图不存在最小生成树
ans += dis[i];
}
return ans;//返回权值和
}
signed main() {
scanf("%d%d", &n, &m);
memset(g, inf, sizeof g);
for (int i = 1; i <= n; ++i) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
g[u][v] = g[v][u] = w;
}
int ans = prim();
cout << ans << endl;
return 0;
}
kruskal :
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<map>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<set>
#include<cctype>
#include<string>
#include<stdexcept>
#include<fstream>
#include<sstream>
#include<sstream>
#define mem(a,b) memset(a,b,sizeof(a))
#define debug() puts("what the fuck!")
#define dedebug() puts("what the fuck!!!")
#define ll long long
#define ull unsigned long long
#define speed {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); };
using namespace std;
const double PI = acos(-1.0);
const int maxn = 2e5 + 10;
const int N = 2e3 + 10;
const ll INF = 1e18;
const ll mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const double esp_0 = 1e-6;
const double gold = (1 + sqrt(5)) / 2;
inline int rd() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch>'9') {
if (ch == '-')f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
ll quick(ll a, ll b) {
ll ans = 1;
while (b) {
if (b % 2) {
ans = ans * a % mod;
}
b >>= 1;
a = a * a % mod;
}
return ans % mod;
}
ll gcd(ll x, ll y) {
return y ? gcd(y, x % y) : x;
}
struct Edge {
int u, v, w;
Edge() {
};
Edge(int u, int v, int w) :u(u), v(v), w(w) {
};
bool operator<(const Edge& a) {
return w < a.w;
}
}edge[110];
int n, m;
int fa[110];
void init() {
for (int i = 1; i <= m; ++i)fa[i] = i;
}
int find(int x) {
return fa[x] == x ? x : find(fa[x]);
}
int uni(int x, int y) {
int fx = find(x);
int fy = find(y);
if (fx != fy) {
fa[fx] = fy;
return 1;
}
return 0;
}
int kruskal() {
int ans = 0;
init();
sort(edge + 1, edge + 1 + n);
for (int i = 1; i <= n; ++i) {
if (uni(edge[i].u, edge[i].v))
ans += edge[i].w;
}
return ans;
}
signed main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
edge[i] = Edge(u, v, w);
}
printf("%d\n", kruskal());
return 0;
}
4. Analizar
prim:
No se utiliza la optimización de la cola de prioridad. Es necesario atravesar cada punto O (V2) y acumular O (V). La complejidad de tiempo total es O (V2 + V), que es aproximadamente O (V2)
kruskal : Sí La complejidad de tiempo de la clasificación de bordes es aproximadamente O (Elog2E), y la operación del conjunto de consultas es O (E), y el total es O (Elog2E + E), que es aproximadamente O (Elog2E)