Постановка задачи
Имея на входе граф G, получить на выходе его остовное дерево минимальной стоимости, использовать алгоритмы Крускала й Прима. Сравнить использованные алгоритмы.
Граф
,
Реализация
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
using namespace std;
const int INF = 10000; // значение "бесконечность"
const int N = 50;
unsigned long long time() {
unsigned long long d;
__asm__ __volatile__ ("rdtsc" : "=A" (d) );
return d;
}
double cpu_speed()
{
unsigned long long t1, t2;
t1=time();
Sleep(500);
t2=time();
return (double) (t2-t1)/500;
}
const double CPU_SPEED = cpu_speed();
void prima(int **g, int n)
{
int moves=0, comps=0;
unsigned long long start, end;
double t = 0;
int out[n][n];
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
out[i][j]=INF;
for(int k=0; k<N; k++)
{
start = time();
vector<bool> used(n, false);
vector<int> min_e(n, INF), sel_e(n, -1);
min_e[0] = 0;
for (int i=0; i<n; ++i) {
int v = -1;
for (int j=0; j<n; ++j) {
if (!used[j] && (v == -1 || min_e[j] < min_e[v])) {
v = j;
moves++;
}
comps++;
}
if (min_e[v] == INF) {
cout << "No MST!";
return;
}
used[v] = true;
if (k==(N-1))
{
out[sel_e[v]][v]=out[v][sel_e[v]]=min_e[v];
}
for (int to=0; to<n; ++to) {
if (g[v][to] < min_e[to]) {
min_e[to] = g[v][to];
sel_e[to] = v;
moves += 2;
}
comps++;
}
comps += (2*n+2);
moves += 5;
}
moves += (3*n+1);
end = time();
t += ((end-start)/CPU_SPEED);
}
ofstream os("prima.txt");
os << n << endl;
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++)
os << out[i][j] << " ";
os << endl;
}
os.close();
cout << "Time = " << t/N << endl;
cout << "Moves = " << (double) moves/N << endl;
cout << "Comps = " << (double) comps/N << endl;
}
void kryskala(int **graph, int n)
{
int moves=0, comps=0;
unsigned long long start, end;
double t = 0;
for(int k=0; k<N; k++) {
vector< pair<int, pair<int,int> > > g; // вес - вершина 1 - вершина 2
for(int i=0; i<n; i++)
for(int j=0; j<n; j++) {
g.push_back(make_pair(graph[i][j], make_pair(i, j)));
}
start = time();
int cost = 0;
vector < pair<int,int> > res;
sort(g.begin(), g.end());
vector<int> tree_id (n);
for(int i=0; i<n; ++i)
tree_id[i] = i;
for(unsigned int i=0; i<g.size(); ++i)
{
int a = g[i].second.first, b = g[i].second.second, l = g[i].first;
moves += 3;
comps++;
if (tree_id[a] != tree_id[b])
{
cost += l;
res.push_back (make_pair (a, b));
int old_id = tree_id[b], new_id = tree_id[a];
moves += 4;
comps += n;
for (int j=0; j<n; ++j)
{
if (tree_id[j] == old_id)
{
tree_id[j] = new_id;
moves++;
}
comps++;
}
}
}
end = time();
comps += (n*n+g.size());
moves += (2*n+1);
t += ((end-start)/CPU_SPEED);
if (k==(N-1))
{
int out[n][n];
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
out[i][j]=INF;
for(int i=0; i<n; i++) {
int a = res[i].first, b = res[i].second;
out[a][b]=out[b][a]=graph[a][b];
}
ofstream os("kryskala.txt");
os << n << endl;
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++)
os << out[i][j] << " ";
os << endl;
}
os.close();
}
}
cout << "Time = " << t/N << endl;
cout << "Moves = " << (double) moves/N << endl;
cout << "Comps = " << (double) comps/N << endl;
}
int main()
{
ifstream is("in.txt");
int n;
is >> n;
int **g = (int **) malloc(n*sizeof(int *));
for(int i=0; i<n; i++) {
g[i] = (int *) malloc(n*sizeof(int));
for(int j=0; j<n; j++)
is >> g[i][j];
}
is.close();
cout << "Prima:" << endl;
prima(g, n);
cout << "Kryskala:" << endl;
kryskala(g, n);
for(int i=0; i<n; i++) free(g[i]);
free(g);
return 0;
}
