这是我在csstack交换中的第一篇文章,我不知道这类问题是否可以在这里发布。
所以我一直在尝试这个问题3天,但我得到了一个解决方案,但是对于隐藏的测试用例来说却失败了。
问题:
每年都会举行一个乡村节日,其中有几组亲戚聚会。为每个人分配一个正整数的标识符.N对亲属标识符作为输入传递。
然后最后给出一个人的标识符I,程序必须打印具有标识符I的人的组中的亲属C的计数。
输入格式: 第一行包含N的值。 N行包含两个相关人员的标识符。 下一行(N + 2)行将包含要打印其组的相对计数的人的标识符I.
输出格式: 第一行将包含具有标识符I的人的组中的亲属C的计数。
边界条件: 1&lt; = N&lt; = 100001&lt; = I <= 1000000
实施例 输入/输出1: 输入:
5
10 20
30 20
40 10
55 35
55 22
40
输出:4
说明:
10,20,30,40组成一个相对组。 55,35,22形成另一个相对组。 因此,标识符为40的人的亲属数为4。
我接触的方法是:
for(auto i = v.begin() ; i!=v.end();i++)
{
if(i->first == r || i->second == r)
{
count+=2;
if(i->first == r)
r = i->second;
else
r = i->first;
remove(v.begin(),v.end(),*i);
n--;
break;
}
}
for(int i =0;i<n;i++)
{
for(int j =0;j<n;j++)
{
if(r == v[j].first || r == v[j].second)
{
if(r == v[j].first)
r = v[j].second;
else
r = v[j].first;
count++;
remove(v.begin(),v.end(),v[j]);
n--;
}
}
}
cout<<count;
那么这个问题的正确解决方案是什么?
答案 0 :(得分:0)
基本上,你的问题是: 给出一个图表,其中节点表示为索引,边缘表示为索引对, 给定一个代表节点的索引i, 找到连接到给定节点的所有节点。
UnionFind算法,用于在具有索引的节点上查找连接的组件:
Initialize an array father of size number of nodes, with father[i] = i
for each edge e consisting of two indices i, j:
ind = i
while(ind != father[ind]) ind = father[ind]
father[j] = ind
for each entry i of the array:
replace father[i] by father[father[i]] until those are equal
之后,同一组件中的所有节点都具有相同的父节点。你用你的数据做到这一点,然后,对于给定的索引i,用father [i] = father [j]找到所有其他索引j。
(运行时间略有改善:将ind设置为最终值后,更新i及其父亲的父亲,依此类推至值ind)
UnionFind的简短说明:它创建了一个树,其中只存储了节点父节点的索引(只需要一个数组)。这是通过迭代边缘来完成的。对于每个边缘,其中一个事件节点的父亲被设置为另一个节点的最高祖先。从本质上讲,我们从单个节点的森林开始,并将它们组装到树上。最后,我们更改剩余的树,以便所有叶子都是根的直接子节点。
由于在您的示例中缺少某些数字,您可能需要创建一些表格,将您的输入索引转换为实际使用的数字范围。但是,如果我们谈论的是一个小的最大指数,比如千分之一,那么就不会这样做。