[英]Problem in finding the diameter of a tree using depth-first search
我正在編寫用於查找樹的最大成本直徑的代碼。 我正在使用深度優先技術,在該技術中我找到離節點最遠的節點(可以是根節點),然后找到離該節點最遠的節點。
例如,如果輸入如下所示:
8
7
1 2 5
2 7 6
2 4 2
4 5 1
4 3 9
1 8 3
8 6 4
其中第一行包含節點數,第二行提到樹中沒有更新。接下來的 n 行包含兩個節點和連接它們的路徑的權重。
相應的輸出應該是:
6
23
這是我的代碼:
#include <iostream>
#include<limits.h>
#include<list>
using namespace std;
int x;
int weight=0;
void dfsutil(int node, int n, int count, int **adj, int &maxcount, bool visited[])
{
visited[node]=true;
count++;
for( auto i=0; i<n; i++)
{
if(!visited[i] && adj[node][i]!=0)
{
if(count>=maxcount)
{
maxcount=count;
weight+=adj[node][i];
x=i;
}
dfsutil(i,n, count, adj, maxcount, visited);
}
}
}
void dfs(int node, int n, int** adj, int &maxcount)
{
bool visited[n+1];
int count=0;
int i;
for(i=1;i<=n;i++)
visited[i]=false;
dfsutil(node, n, count+1, adj, maxcount, visited);
}
int diameter(int n, int **adj)
{
int maxcount;
maxcount=INT_MIN;
dfs(1,n,adj,maxcount);
dfs(x,n,adj,maxcount);
return maxcount;
}
int main()
{
int n,q,i,q1,q2,w;
cout<<"Enter the number of nodes in the tree"<<endl;
cin>>n;
cout<<"Enter the number of queries"<<endl;
cin>>q;
int **adj=new int *[n];
for(i=0;i<n;i++)
{
adj[i]=new int[n];
}
for(i=1;i<=q;i++)
{
cin>>q1>>q2>>w;
adj[q1-1][q2-1]=w;
adj[q2-1][q1-1]=w;
}
cout<<"The diameter is "<<diameter(n,adj)<<endl;
return 0;
}
這段代碼存在兩個問題:
i) 輸出應該是 6 而我得到 4。我找不到什么問題。
ii) 如果兩個或多個葉節點處於同一級別但具有不同的權重,則最大成本直徑應選擇總權重最大的路徑。 例如這里,對於權重為9
和1
的4->3
和4->5
,計算直徑時可以考慮路徑中的任何一個,但在計算成本時,權重為9
的路徑即4->3
應選擇4->3
。 如何檢查這種情況?
在檢查你的代碼后,我發現了幾個錯誤。 例如,您的dfsUtil
實現不正確。 由於它是一棵加權樹,因此您應該根據邊權重進行比較,而不是計算節點數。 你的索引也是一團糟。 一致地使用基於0
的索引或基於1
的索引。 混合使用其中的兩個會使調試變得更加困難。 最后,您要向函數傳遞大量信息。 您應該將這些信息封裝在一個class
。 它使您的生活變得更加輕松。 以下是我對您要實現的目標的看法:
#include <iostream>
#include <vector>
class Edge{
public:
int node,weight;
Edge() = default;
Edge(int n, int w) : node(n), weight(w) {}
};
class TreeDiameterInfo{
public:
int endPointA, endPointB, diameter;
TreeDiameterInfo() = default;
TreeDiameterInfo(int eA, int eB, int d) : endPointA(eA), endPointB(eB), diameter(d){}
};
class Graph{
static constexpr int MAX_NODE = 100;
int nodes,edges;
std::vector <Edge> adjList[MAX_NODE + 5];
std::vector <int> visited;
std::vector <int> distance;
public:
Graph() = default;
void addEdge(int nodeA, int nodeB,int weight){
adjList[nodeA].emplace_back(Edge(nodeB,weight));
adjList[nodeB].emplace_back(Edge(nodeA,weight));
}
void takeInput(){
std::cin >> nodes >> edges;
for(int i = 0 ; i < edges ; ++i){
int endA,endB,weight;
std::cin >> endA >> endB >> weight;
addEdge(endA,endB,weight);
}
}
void printGraph(){
std::cout << "===== Printing Graph =====\n";
for(int i = 1 ; i <= nodes ; ++i){
std::cout << "Node " << i << ": ";
for(int j = 0 ; j < adjList[i].size() ; j++){
std::cout << "(" << adjList[i][j].node << "," << adjList[i][j].weight << ")";
if(j != adjList[i].size() - 1) std::cout << " ";
}
std::cout << "\n";
}
}
void dfs(int source, int &bestDistance, int &bestNode){
visited[source] = 1;
for(int i = 0 ; i < adjList[source].size() ; ++i){
int adjacentNode = adjList[source][i].node;
int costToNode = adjList[source][i].weight;
if(!visited[adjacentNode]){
distance[adjacentNode] = distance[source] + costToNode;
if(bestDistance < distance[adjacentNode]){
bestDistance = distance[adjacentNode];
bestNode = adjacentNode;
}
dfs(adjacentNode, bestDistance, bestNode);
}
}
}
void initialize(){
visited = std::vector <int> (MAX_NODE + 5, 0) ;
distance = std::vector <int> (MAX_NODE + 5, 0) ;
}
TreeDiameterInfo treeDiameter(){
int farthestNodeFromRoot = -1, distanceFromRoot = -1;
initialize();
dfs(1, distanceFromRoot, farthestNodeFromRoot);
int farthestNodeFromDiameterEndPoint = -1, farthestDistanceFromDiameterEndPoint = -1;
initialize();
dfs(farthestNodeFromRoot, farthestDistanceFromDiameterEndPoint, farthestNodeFromDiameterEndPoint);
return TreeDiameterInfo(farthestNodeFromRoot, farthestNodeFromDiameterEndPoint, farthestDistanceFromDiameterEndPoint);
}
};
int main(){
Graph g;
g.takeInput();
g.printGraph();
TreeDiameterInfo treeDiameterInfo = g.treeDiameter();
std::cout << "Tree Diameter: " << treeDiameterInfo.diameter << "\n";
std::cout << "Two end points of tree diameter: " << treeDiameterInfo.endPointA << " " << treeDiameterInfo.endPointB << "\n";
return 0;
}
輸出:
===== Printing Graph =====
Node 1: (2,5) (8,3)
Node 2: (1,5) (7,6) (4,2)
Node 3: (4,9)
Node 4: (2,2) (5,1) (3,9)
Node 5: (4,1)
Node 6: (8,4)
Node 7: (2,6)
Node 8: (1,3) (6,4)
Tree Diameter: 23
Two end points of tree diameter: 3 6
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.