簡體   English   中英

使用深度優先搜索找到樹的直徑的問題

[英]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) 如果兩個或多個葉節點處於同一級別但具有不同的權重,則最大成本直徑應選擇總權重最大的路徑。 例如這里,對於權重為914->34->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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM