- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在 hackerrank 上做这个名为 Even Tree 的问题:
https://www.hackerrank.com/challenges/even-tree
一开始我不知道如何切割边缘并从树中 build 森林。所以我在网上查了一下,在 stackeverflow 上看到了这个答案:
Obtain forest out of tree with even number of nodes
好吧,只计算 child 的数量看起来简单多了,我用 C++ 实现了它:
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main() {
int N, M, ans = 0;
cin >> N >> M;
vector<int> tree(N+1);
vector<int> count(N+1);
fill(count.begin(), count.end(), 1);
for(int i = 0; i < M; i++) {
int p, q;
cin >> p >> q;
tree[p] = q;
int root = tree[p];
// updating ancesors child count
while(root) {
count[root] += count[p];
root = tree[root];
}
}
int counter = 0;
// displaying results
for(int i = 2; i < count.size(); i++) {
cout << count[i] << " ";
if(count[i]%2 == 0)
counter++;
}
cout <<"\nans : " << counter << endl;
return 0;
}
我的问题是:这种方法如何运作?有多少 child 与选择边数最少的树有关?我不只是想复制解决方案,我想了解其背后的实际逻辑。请帮忙
最佳答案
首先,问题说所有测试用例(所有输入树),存在一种删除边缘的方法,以便保留森林的均匀大小。当然,由于结果森林中的每棵树的大小都是偶数,这意味着节点总数 N 必须是偶数。偶数树必须有解,因为它们至少可以移除 0 条边以形成偶数森林。
注意有一些边不能被移除,即连接叶节点的边。于是我脑子里冒出一些贪心的想法,结果证明我可以证明它们,所以它们成为可以解决问题的贪心算法。
我声称
a) 任何偶数大小的子树,我们可以安全地从原始图中删除它们以减少问题而不影响结果,方法是删除子树根及其父节点的边(如果存在) )
b) 任何奇数大小的子树,我们可以用单个节点替换整个子树以减少问题。子树根的边及其父不能被删除(如果存在)
我们用反证法证明a)。假设如果我们删除图的偶数子树将使问题从可解变为不可解。考虑去掉偶数子树后的图,如果是奇数,则原图也无解;如果它的大小是偶数,那么它必须在删除偶数子树后有解决方案。这两种情况都会产生矛盾。
b) 非常简单,因为子树是奇数大小,其奇偶校验与单个叶节点相同,必须与其父节点连接。所以我们可以用单个节点替换子树来减少问题。
通过a)和b),我们可以从树的叶子做贪心算法(因为我们已经知道必须选择连接叶子的边,他们正在形成子树,我们可以从这里开始减少问题)
就是这样。从概念上讲,这就是算法。
虽然您可以使用许多不同的方法来实现它,但我使用 DFS,它非常直接地将此算法转换为代码。
一些简单地计算子树的数量,因为这可以判断子树是奇数还是偶数。
有人甚至只计算偶数度的节点数! (这是迄今为止我所知道的最聪明的解决方案)
但它们背后都有相同的概念:判断子树是否为奇数大小或偶数大小,删除它们(并增加答案计数器)或用单个节点替换它们以减少问题。
所有实现也具有相同的复杂度 O(N)。
这是我接受的代码:
#include<bits/stdc++.h>
using namespace std;
int w[105][105] = {0}, v[105] = {0};
int n,m,ans=0;
int dfs(int x){
v[x] = 1;
int son = 0;
for(int i=0; i<105;i++)
if(w[x][i] && !v[i]) son += dfs(i);
if(son % 2) { ans++; return 0;}
return 1;
}
int main() {
scanf("%d%d", &n,&m);
for(int i=0,a,b; i<m;i++){
scanf("%d%d", &a,&b);
w[a][b] = w[b][a] = 1;
}
dfs(1);
printf("%d\n", ans-1);
return 0;
}
关于algorithm - hackerrank偶数树解法讲解(偶数节点的森林),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35078435/
我有一个包含多个数字的数组: int[] tab = {1,2,3,4}; 我必须创建两个方法,第一个是 sum() 方法,第二个是 numberOdd()。 这一步就OK了! int length
我一直在研究这个简单的待办事项列表,现在正处于调试阶段。当我实现不同的更改时,我观察到以下情况 保留列表中的所有项目:我添加 1 项,没问题。我添加了 2 个项目,但没有任何效果 - 无法标记完整/不
我想仅在未引用的术语中将 | 替换为 OR,例如: "this | that" | "the | other" -> "this | that" OR "the | other" 是的,我可以分割空格
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 7 年前。 Improve this ques
我在一些练习中得到了这个示例代码,它展示了如何查找整数是奇数还是偶数。 int x = 4; if ( (x & 1) == 0 ) { System.out.prin
我无法制作简单的 JavaScript 来获取文本框中的数字,并在单击按钮时返回结果。 function check() { var v=document.getElem
我是一名初学者,我正在尝试创建一个程序,该程序将生成仅由偶数组成的数字,并四舍五入到最接近的偶数。 例子: 135 --> 200 2700 --> 2800 我有一个代码,但每当我尝试打印它时,数字
我正在尝试编写一个程序,它将接受两个数字并根据它们的值返回两个都是奇数,两个都是偶数,或者 A 是奇数而 B 是偶数,等等。 我设法让程序检查一个变量,但如果我添加第二个变量,我会得到一个我不期望的输
这是一个带有数据和下一个属性的标准链表。 这就是我正在尝试的: class Node { constructor(data, next) { this.data = data;
我有一个正则表达式问题,我不知道该怎么做。它必须匹配开头包含任意数量的 a 的所有字符串,然后如果 a 的数量是偶数则匹配单个 0,如果 a 的数量是奇数则匹配单个 1。 如何跟踪偶数/奇数? 示例
我试图在数组中执行一个循环,对内容进行排序并创建每个具有 2 个值的 div。 尝试了很多东西,但我不知道我需要做什么。 这就是我需要做的:在数组中循环并创建 div。每个 div 应该有 2 个数组
您好,想知道是否有更简单的方法来显示奇数/偶数。我知道我可以做一个 for 循环并加载一个列表。然后我可以写另一个for循环遍历列表并检查值是否为奇数/偶数: for(i=0; i i % 2 ==
我正在尝试改变边距以使图像上下呈之字形。我发现this article很接近,但将一项更改应用于所有 .brochureImg 类。我做错了什么? HTML GP &
我编写这个方法来重新排列两个堆栈的元素,使堆栈 s1 只包含偶数整数,堆栈 s2 只包含奇数整数。并且 s1 或 s2 中不应存储任何零。 public static void rerange(sta
我需要帮助才能将未知整数分成给定数量的偶数部分——或者至少尽可能地均匀。各部分之和应为原值,但各部分应为整数,且应尽可能接近。 参数 num: Integer - 应该被分成相等部分的数字 parts
我在这里想做的是由偶数消费者打印偶数,由奇数消费者打印奇数。 有一个 evenodd 方法,它基本上消耗任何数字并打印(无论是偶数还是奇数)。我有 2 个偶数消费者线程、2 个奇数消费者线程、2 个偶
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
谁能帮忙。我必须编写一个程序,让用户输入 10 个数字。并将这些数字按奇数(升序)和偶数(降序)排序。 例如:输入:2、8、7、13、23、9、34、11、1、16输出:1、7、9、11、13、23、
给定两个列表,我想合并它们,以便第一个列表中的所有元素都是偶数索引(保留它们的顺序),第二个列表中的所有元素都是奇数索引(也保留它们的顺序)。示例如下: x = [0,1,2] y = [3,4] r
我有一个表,对列和行进行求和,并显示求和的结果。我必须改变每个总数的颜色。如果是偶数,则将其设置为“绿色”。如果是奇数,则将其设置为“红色” 这是我的 table :
我是一名优秀的程序员,十分优秀!