PAT 1021 Deepest Root
16650 ワード
#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であるべきで、これを利用して最適化すると速度がかなり速くなるはずです.午後に1発書き換えて、時間はもとの1200 msが15 msに下がったことがあって、利用問題の中の法則はやはり必要であることを見ることができます:
#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;
}