简体   繁体   中英

Problem in finding the diameter of a tree using depth-first search

I am writing the code for finding the maximum cost diameter of a tree. I am using depth first technique in which I find out the farthest node from the node(which can be the root node) and then find the farthest node from that node.

For example if the input looks like this:

8
7
1 2 5
2 7 6
2 4 2
4 5 1
4 3 9
1 8 3
8 6  4

Where 1st line contains the no of nodes, 2nd line mentions no of updations in the tree.The next n lines contains the two nodes and the weight of the path joining them.

The corresponding output should be:

6
23

Here is my code :

#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;
}

There is two problem that exist in this code:

i) The output should be 6 instead I get 4. What is the problem I can't find out.

ii) What if when two or more leaf nodes are at the same level but have different weights, the maximum cost diameter should take the path with maximum total weights. For example here, in case of 4->3 and 4->5 which have weights 9 and 1 and any one of the path can come into consideration while calculating diameter but while calculating the cost, the path with weight 9 ie, 4->3 should be chosen. How to check for this condition?

After going through your code, I've found several mistakes. For example, your dfsUtil implementation is not correct. As it is a weighted tree, you should be comparing based on the edge weights, not on counting the number of nodes. Your indexing is also a mess. Either use a 0 based indexing or 1 based indexing consistently. Mixing two of these makes debugging a lot harder. Lastly, you're passing a lot of information to the function. You should encapsulate this information inside a class . It makes your life a whole lot easier. Below is my take on what you're trying to achieve:

#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;
}

Output:

===== 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM