Как обнаружить цикл в граничном представлении графа?

Я написал структуру графа в виде списка ребер и пытаюсь написать алгоритм MST Крускала для него.

Вот мой код до сих пор:

#include <bits/stdc++.h>
using namespace std;
struct _ { ios_base::Init i; _() { cin.sync_with_stdio(0); cin.tie(0); } } _;

//////////////////////////////////////////////////////////////////////////////////
#define endl '\n'
#define ll long long
#define pb push_back
#define mt make_tuple
#define in(a) for (auto& i: a)
//////////////////////////////////////////////////////////////////////////////////

#define edge tuple < ll, ll, ll >

bool func (edge a, edge b) { return get<2>(a) < get<2>(b); }

struct graph
{
ll v;
vector <edge> edgelist;
void addedge (edge x) { edgelist.pb(x); }
ll find (vector <ll> parent, ll i)
{ return parent[i]==-1 ? i : find (parent, parent[i]); }
bool cycle()
{
vector <ll> parent (v);
fill (parent.begin(), parent.end(), -1);
in (edgelist)
{
ll x = find (parent, get<0>(i));
ll y = find (parent, get<1>(i));
if (x==y) return true;
else parent[x]=y;
}
return false;
}

graph mst()
{
sort (edgelist.begin(), edgelist.end(), func);
graph tree;
in(edgelist)
{
graph temp = tree;
temp.addedge(i);
if (!temp.cycle()) tree=temp;
}
return tree;
}

};int main()
{
graph g;
cin >> g.v;
ll e;
cin >> e;
for (ll i=1; i<=e; i++)
{
ll a, b, w;
cin >> a >> b >> w;
g.addedge(mt(a, b, w));
}
graph mstree = g.mst();
in(mstree.edgelist) cout << get<0>(i) << " " << get<1>(i) << " " << get<2>(i) << endl;
cout << endl;

}

/*
Sample Input
4 5
0 1 10
0 2 6
0 3 5
1 3 15
2 3 4

Sample Output
2 3 4
0 3 5
0 1 10
*/

Мой код занимает очень много времени, чтобы произвести вывод. Есть ли проблемы в моей реализации? Кроме того, если я повторяю эту задачу для нескольких графиков, моя программа падает в середине выполнения.

0

Решение

Мой код занимает очень много времени, чтобы произвести вывод. Есть ли
проблемы в моей реализации?

Есть несколько проблем:

Первый,

ll find (vector <ll> parent, ll i)
{ return parent[i]==-1 ? i : find (parent, parent[i]); }

Вы передаете parent по значению это означает копирование всего массива. Передайте по ссылке (и неконстантно, так как вам нужно будет изменить ее, см. Пункт 3).

Во-вторых, в cycle() вам не нужно проверять все ребра, вам нужно проверить только ребро, которое рассматривается в основном цикле (в mst()). (И не устанавливать parent в cycle()необходимо использовать один и тот же массив во всех mst().)

В-третьих, читайте об «улучшениях» структуры разъединения (даже Статья в википедии объяснил все это), а именно объединение по рангу и сжатию пути. Только с теми вы достигнете ожидаемой производительности от разъединения.

Кроме того, если я повторяю эту задачу для нескольких графиков, моя программа падает
середина исполнения.

Невозможно сказать, не зная, как вам петля и каковы несколько графиков входы, которые вы используете. Тем не менее, я сильно подозреваю, что переполнение стека на графиках даже среднего размера при прохождении parent по значению, таким образом быстро потребляя стек.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]