PAT 1021 Deepest Root

#include <cstdio>
#include <cstdlib>
#include <vector>

using namespace std;

class Node {
public:
    vector<int> adj;
    bool visited;
    Node() : visited(false) {}
};

void reset_nodes(vector<Node>& nodes) {
    int len = nodes.size();
    for (int i=0; i<len; i++) {
        nodes[i].visited = false;
    }
}

void dfs(int idx, vector<Node>& nodes, int level, int& deepest) {
    if (nodes[idx].visited) return;
    Node& node = nodes[idx];
    node.visited = true;
    if (level > deepest) deepest = level;
    
    int len = node.adj.size();
    for (int i=0; i<len; i++) {
        dfs(node.adj[i], nodes, level + 1, deepest);
    }
}

int find_deepest_from(int idx, vector<Node>& nodes) {
    int deepest = 0;
    // reset visited flag of all the nodes
    reset_nodes(nodes);
    
    // find the max level from this node(as root)
    dfs(idx, nodes, 0, deepest);
    
    int parts = 1;
    // check if other parts exist
    for (int i = nodes.size() - 1; i>=1; i--) {
        if (!nodes[i].visited) {
            int dummy = 0;
            dfs(i, nodes, 0, dummy);
            parts++;
        }
    }
    
    return parts > 1 ? -parts : deepest;
}

int main() {
    int N = 0;
    scanf("%d", &N);

    vector<Node> nodes(N + 1);
    
    for (int i=1; i<N; i++) {
        int a, b;
        scanf("%d%d", &a, &b);
        nodes[a].adj.push_back(b);
        nodes[b].adj.push_back(a);
    }
    
    int res = 0;
    vector<int> deepnodes;
    int deepest = 0;
    for (int i=1; i<=N; i++) {
        res = find_deepest_from(i, nodes);
        // not connected graph, stop search
        if (res < 0) {
            break;
        }
        if (res > deepest) {
            deepest = res;
            deepnodes.clear();
            deepnodes.push_back(i);
        } else if (res == deepest) {
            deepnodes.push_back(i);
        }
    }
    if (res < 0) {
        printf("Error: %d components
", -res);
    } else {
        int len = deepnodes.size();
        for (int i=0; i<len; i++) {
            printf("%d
", deepnodes[i]);
        }
    }
    return 0;
}

最深root的最远leaf也应该是最深root,利用这个做下优化的话速度应该会快不少。下午改写了一发,时间就有原来的1200ms降到了15ms,可见利用问题中的规律还是很有必要的:

#include <cstdio>
#include <cstdlib>
#include <vector>
#include <set>

using namespace std;

class Node {
public:
    vector<int> adj;
    bool visited;
    Node() : visited(false) {}
};

void reset_nodes(vector<Node>& nodes) {
    int len = nodes.size();
    for (int i=0; i<len; i++) {
        nodes[i].visited = false;
    }
}

void dfs(int idx, vector<Node>& nodes, int level, int& deepest, set<int>& leaf) {
    if (nodes[idx].visited) return;
    Node& node = nodes[idx];
    node.visited = true;
    if (level > deepest) {
        deepest = level;
        leaf.clear();
        leaf.insert(idx);
    } else if (level == deepest) {
        leaf.insert(idx);
    }
    
    int len = node.adj.size();
    for (int i=0; i<len; i++) {
        dfs(node.adj[i], nodes, level + 1, deepest, leaf);
    }
}

int find_deepest_from(int idx, vector<Node>& nodes, set<int>& leaf) {
    int deepest = 0;
    // reset visited flag of all the nodes
    reset_nodes(nodes);
    
    // find the max level from this node(as root)
    dfs(idx, nodes, 0, deepest, leaf);

    int parts = 1;
    // check if other parts exist
    set<int> dummy_leaf;
    int dummy_deepest = 0;
    for (int i = nodes.size() - 1; i>=1; i--) {
        if (!nodes[i].visited) {
            dummy_leaf.clear();
            dummy_deepest = 100000;
            dfs(i, nodes, 0, dummy_deepest, dummy_leaf);
            parts++;
        }
    }
    if (parts > 1) return -parts;
    
    reset_nodes(nodes);
    vector<int> root(leaf.begin(), leaf.end());
    int len = root.size();
    
    for (int i=0; i<len; i++) {
        dfs(root[i], nodes, 0, deepest, leaf);
        leaf.insert(root[i]);
    }
    
    return parts > 1 ? -parts : deepest;
}

int main() {
    int N = 0;
    scanf("%d", &N);

    vector<Node> nodes(N + 1);
    
    for (int i=1; i<N; i++) {
        int a, b;
        scanf("%d%d", &a, &b);
        nodes[a].adj.push_back(b);
        nodes[b].adj.push_back(a);
    }
    
    int res = 0;
    set<int> deepnodes;
    int deepest = 0;
    res = find_deepest_from(1, nodes, deepnodes);
    // not connected graph
    if (res < 0) {
        printf("Error: %d components
", -res);
    } else {
        auto iter = deepnodes.begin();
        while (iter != deepnodes.end()) {
            printf("%d
", *iter++);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lailailai/p/4028220.html