2016-S3 Phonomenal Reviews - Solution

2016-S3 Phonomenal Reviews - Solution

Node Graph

struct Node
{
    int id;
    bool isPhoRestaurant;
    vector<int> connections;
};
 
int numberOfRestaurants, numberOfPhoRestaurants;
vector<int> phoRestaurants;
vector<Node> nodes;
 
void initGraph()
{
    nodes = vector<Node>();
    for (int i = 0; i < numberOfRestaurants; i++)
    {
        Node node = Node();
        node.id = i;
        node.isPhoRestaurant = false;
        node.connections = vector<int>();
        nodes.push_back(node);
    }
    phoRestaurants = vector<int>();
}
 
void addPhoRestaurant(int pho)
{
    phoRestaurants.push_back(pho);
    nodes[pho].isPhoRestaurant = true;
}
 
void addConnection(int a, int b)
{
    nodes[a].connections.push_back(b);
    nodes[b].connections.push_back(a);
}

Read Input

void readInput()
{
    cin >> numberOfRestaurants >> numberOfPhoRestaurants;
    initGraph();
    for (int i = 0; i < numberOfPhoRestaurants; i++)
    {
        int pho;
        cin >> pho;
        addPhoRestaurant(pho);
    }
    for (int i = 0; i < (numberOfRestaurants - 1); i++)
    {
        int a, b;
        cin >> a >> b;
        addConnection(a, b);
    }
}

Get Farthest Pho Restaurant

void depthFirstSearch(int startingNode, int previousNode, int distanceToStartingNode, int &maxDistanceNode, int &maxDistance)
{
    for (int i = 0; i < nodes[startingNode].connections.size(); i++)
    {
        int currentNode = nodes[startingNode].connections[i];
        if (currentNode != previousNode)
        {
            int distanceToCurrentNode = distanceToStartingNode + 1;
            if (distanceToCurrentNode > maxDistance && nodes[currentNode].isPhoRestaurant)
            {
                maxDistance = distanceToCurrentNode;
                maxDistanceNode = currentNode;
            }
            depthFirstSearch(currentNode, startingNode, distanceToCurrentNode, maxDistanceNode, maxDistance);
        }
    }
}
 
void getFarthestPhoRestaurant(int startingNode, int &maxDistanceNode, int &maxDistance)
{
    depthFirstSearch(startingNode, startingNode, 0, maxDistanceNode, maxDistance);
}

Solve Tree

bool *doesSubtreeContainPhoRestaurant;
 
void solveAllDoesSubtreeContainPhoRestaurant(int startingNode, int previousNode)
{
    Node node = nodes[startingNode];
    if (node.isPhoRestaurant == true)
    {
        doesSubtreeContainPhoRestaurant[startingNode] = true;
    }
    for (int i = 0; i < node.connections.size(); i++)
    {
        int currentNode = node.connections[i];
        if (currentNode != previousNode)
        {
            solveAllDoesSubtreeContainPhoRestaurant(currentNode, startingNode);
            if(doesSubtreeContainPhoRestaurant[currentNode] == true)
            {
                doesSubtreeContainPhoRestaurant[startingNode] = true;
            }
        }
    }
}
 
void solveSubtree(int startingNode, int previousNode, int &cost)
{
    Node node = nodes[startingNode];
    for (int i = 0; i < node.connections.size(); i++)
    {
        int currentNode = node.connections[i];
        if (currentNode != previousNode)
        {
            if (doesSubtreeContainPhoRestaurant[currentNode])
            {
                cost += 2;
                solveSubtree(currentNode, startingNode, cost);
            }
        }
    }
}
 
int solveTree(int startingNode)
{
    doesSubtreeContainPhoRestaurant = new bool[numberOfRestaurants];
    memset(doesSubtreeContainPhoRestaurant, false, numberOfRestaurants * sizeof(bool));
    solveAllDoesSubtreeContainPhoRestaurant(startingNode, startingNode);
    int cost = 0;
    solveSubtree(startingNode, startingNode, cost);
    delete doesSubtreeContainPhoRestaurant;
    return cost;
}

Main Method

int main()
{
    readInput();
    int maxDistance = 0, optimalStartingNode = 0, optimalEndingNode = 0;
    getFarthestPhoRestaurant(phoRestaurants[0], optimalStartingNode, maxDistance);
    int cost = solveTree(optimalStartingNode);
    getFarthestPhoRestaurant(optimalStartingNode, optimalEndingNode, maxDistance);
    int finalCost = cost - maxDistance;
    cout << finalCost;
    return 0;
}