https://i.stack.imgur.com/JAz2M.png
这是问题所在。 我有密码。但以某种方式无法通过所有测试用例。我生成的所有测试用例都是真实的。你能告诉我为什么我弄错了吗?
将为您提供N个目录/文件夹的目录树。每个目录都由一个从1到N的特定目录表示。根目录的ID为1,那么它有一些子目录,这些目录可能包含其他一些目录,然后继续。现在,您将获得要删除的目录ID的列表,您需要找到需要删除的最小目录数,以便删除给定列表中的所有目录。
vector<vector<int> > adj;
vector<bool> del;
vector<bool> col;
void Final(int a, bool val)
{
col[a] = val;
if (del[a])
val = del[a];
for (int i = 0; i < adj[a].size(); i++) {
Final(adj[a][i], val);
}
return;
}
int main()
{
int n;
cin >> n;
adj.resize(n + 1);
adj.clear();
for (int i = 1; i <= n; i++) {
int a;
cin >> a;
adj[a].push_back(i);
}
int q;
cin >> q;
if (q <= 1) {
cout << q << endl;
return 0;
}
del.resize(n + 1);
col.resize(n + 1);
del.clear();
col.clear();
for (int i = 0; i <= n; i++) {
col[i] = false;
del[i] = false;
}
for (int i = 0; i < q; i++) {
int a;
cin >> a;
del[a] = true;
}
if (del[1]) {
cout << "1" << endl;
return 0;
}
else {
Final(1, false);
int final = q;
for (int i = 1; i <= n; i++) {
if (del[i] && col[i])
final--;
}
cout << final << " ";
}
}
答案 0 :(得分:1)
使用DFS!
如果根标记为“待删除”,则返回1(这是最好的情况,工作最少)。否则,递归到根的每个子节点,并将它们加起来以知道要删除的节点数。不变的是:如果要删除节点,请不要再重新使用子树(因为植根于该子树的所有内容都会消失)
这是一些伪代码
DFS(root)
if(root is to be deleted)
return 1
else
number_of_nodes_to_delete = 0;
for every child c of root
number_of_nodes_to_delete += DFS(c)
return number_of_nodes_to_delete;
您显然有正确的想法将树表示为邻接列表vector<vector<int>>
。
作为次要细节,将邻接列表作为const&
传递到递归中。这样可以节省复印时间。 (DFS(int root, const vector<vector<int>>& adjList
可能是有用的函数签名)。
答案 1 :(得分:0)
我已经使用Java解决了同样的问题。下面是代码。
// Function to add an edge into the graph
void addEdge(int v, int w) {
adj[v].add( w); // Add w to v’s list.
}
public int DFS(int s, Set<Integer> tset) {
// Store the DFS travel which does not contain child nodes to be deleted
List<Integer> dfs_travel = new Vector<>();
// Initially mark all vertices as not visited
List<Boolean> visited = new Vector<Boolean>(V);
for (int i = 0; i <= V; i++)
visited.add(false);
// Create a stack for DFS
Stack<Integer> stack = new Stack<>();
// Push the current source node
stack.push(s);
while (stack.empty() == false) {
// Pop a vertex from stack and print it
s = stack.pop();
// Stack may contain same vertex twice. So
// we need to print the popped item only
// if it is not visited.
// Also check whether the element is part of elements to be remove
if (visited.get(s) == false && tset.contains(s)) {
dfs_travel.add(s);
visited.set(s, true);
}
// Get all adjacent vertices of the popped vertex s
// If a adjacent has not been visited,
// and it is not in delete set then push it
// to the stack.
if (!tset.contains(s)) {
Iterator<Integer> itr = adj[s].iterator();
while (itr.hasNext()) {
int v = itr.next();
if (!visited.get(v))
stack.push(v);
}
}
}
return dfs_travel.size();
}
private int processDirectoryDeletion(int n, int[] folders, int m,
int[] idsTodelete) {
TestClass g = new TestClass(n);
Set<Integer> tset = new HashSet<Integer>();
for (int i = 0; i < idsTodelete.length; i++) {
tset.add(idsTodelete[i]);
}
g.addEdge(0, 1);
int ans = 0;
for (int i = 1; i < n; i++) {
g.addEdge(folders[i], i + 1);
}
return g.DFS(1, tset);
}