На самом деле эта функция не вычисляет диаметр. Он вычисляет самую удаленную вершину из заданной вершины v
.
Для вычисления диаметра дерева, вам нужно сначала выбрать произвольную вершину (скажем v
), а затем найти вершину, которая дальше от v
(скажем w
), а затем найти вершину, которая дальше от w
, давайте сядем u
. Расстояние между w
и u
- это диаметр дерева, но расстояние между v
и w
(что делает ваша функция) не гарантируется как диаметр.
Чтобы ваша функция вычислила диаметр, вам нужно будет вернуть верхушку, найденную рядом с расстоянием. Удобно, что это всегда будет последний элемент, который вы обрабатываете, поэтому просто заставьте свою функцию запомнить последний обработанный элемент вместе с расстоянием до этого элемента и вернуть их оба. Затем дважды вызовите свою функцию, сначала из любой произвольной вершины, затем из вершин, которые возвратил первый вызов.
Чтобы на самом деле найти центр, вы также можете вспомнить родителя для каждого узла во время вашей BFS. Для этого выделить дополнительный массив, скажем prev
, и когда вы делаете
dist[nghbr] = dist[pos] + 1;
также сделать
prev[nghbr] = pos;
Затем в конце второго вызова функции, вы можете просто сходить bdist/2 раза в предыд, что-то вроде:
center = lastVertex;
for (int i = 0; i + i < bdist; ++ i) center = prev[center];
Так с небольшими ухищрениями к вашей функции (что делает его вернуть дальнюю вершину из v
и вершины, которая находится на середине dle этого пути и вообще не возвращать диаметр), этот код, скорее всего, вернет вам центр дерева (я тестировал его только на вашем примере, поэтому он может быть отключен на один из ошибок)
pair<int, int> biggest_dist(int n, int v, const vector< vector<int> >& graph)
{
int INF = 2 * graph.size(); // Bigger than any other length
vector<int> dist(n, INF);
vector<int> prev(n, INF);
dist[v] = 0;
queue<int> next;
next.push(v);
int bdist = 0; //biggest distance
int lastV = v;
while (!next.empty()) {
int pos = next.front();
next.pop();
bdist = dist[pos];
lastV = pos;
for (int i = 0; i < graph[pos].size(); ++i) {
int nghbr = graph[pos][i];
if (dist[nghbr] > dist[pos] + 1) {
dist[nghbr] = dist[pos] + 1;
prev[nghbr] = pos;
next.push(nghbr);
}
}
}
int center = lastV;
for (int i = 0; i + i < bdist; ++ i) center = prev[center];
return make_pair(lastV, center);
}
int getCenter(int n, const vector< vector<int> >& graph)
{
// first call is to get the vertex that is furthest away from vertex 0, where 0 is just an arbitrary vertes
pair<int, int> firstResult = biggest_dist(n, 0, graph);
// second call is to find the vertex that is furthest away from the vertex just found
pair<int, int> secondResult = biggest_dist(n, firstResult.first, graph);
return secondResult.second;
}
Для деревьев есть симпатичный алгоритм, который вы можете использовать: одновременно удалите все листы на графике и повторите это, пока вы не останетесь с одним или двумя узлами. Эти оставшиеся узлы являются центрами. Будет ли это работать для вас, или вы специально хотите работать с вышеуказанным кодом? – templatetypedef
Ухх ... вы могли бы просто рассматривать его как график и dfs от u до t, а затем возвращать диаметр/2 раза. Или, если это по-настоящему более удобно, поскольку дерево по какой-то причине вы могли бы корень дерева, найти все глубины, а затем найти (диаметр/2) -го родителя нижнего узла ... (я думаю?) РЕДАКТИРОВАТЬ: как ваш код находит диаметр графика, он, кажется, просто находит самое далекое расстояние от узла v? – quasiverse