简体   繁体   English

使用深度优先搜索找到树的直径的问题

[英]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.其中第一行包含节点数,第二行提到树中没有更新。接下来的 n 行包含两个节点和连接它们的路径的权重。

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. i) 输出应该是 6 而我得到 4。我找不到什么问题。

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. ii) 如果两个或多个叶节点处于同一级别但具有不同的权重,则最大成本直径应选择总权重最大的路径。 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.例如这里,对于权重为914->34->5 ,计算直径时可以考虑路径中的任何一个,但在计算成本时,权重为9的路径即4->3应选择4->3 How to check for this condition?如何检查这种情况?

After going through your code, I've found several mistakes.在检查你的代码后,我发现了几个错误。 For example, your dfsUtil implementation is not correct.例如,您的dfsUtil实现不正确。 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.一致地使用基于0的索引或基于1的索引。 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 .您应该将这些信息封装在一个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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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