题目名称:可疑的记录
题目链接:可疑的记录
描述
小Hi有一棵N个节点的树,编号1-N,其中1号节点是整棵树的根。他把这棵树的N-1条边记录成N-1行,每行2个整数a和b,表示a是b的父节点。
喜欢恶作剧的小Ho在小Hi的记录里加了一行两个整数,于是小Hi不得设法找出这行可疑的记录。具体来说,如果去掉某一行之后,余下N-1行按小Hi的规则(a是b的父节点)恰好能构成一棵N个节点的树,并且满足编号恰好是1-N且1号节点是根,那么被去掉的一行就被视为可疑的。
你能帮小Hi找出所有可疑的记录吗?
输入
第一行包含一个整数N,表示树的节点数目。
以下N行每行两个整数a和b,表示a是b的父节点。
对于30%的数据,1 <= N <= 1000
对于100%的数据, 1 <= N <= 100000, 1 <= a, b <= N
输入保证合法。
输出
输出一行包含若干个从小到大的整数,表示可疑的行号。(行号从1开始)
样例输入
3
1 2
1 3
1 3
样例输出
2 3
解题思路
第一眼看上去觉得需要使用搜索算法,不过后来想了想,只加了一组数据,所以有一个节点一定右两个父节点,只需要找到这个节点所在行的位置就可以,所以使用vector对每个节点的父节点进行统计
如果发现图中1号节点有父节点,那么必然1号节点到它父节点这条边是可疑的,直接输出其编号即可。
如果1号节点没有父节点,那么必然有某个节点有2个父节点。那么从这个节点到它2个父节点这2条边都可能是答案。
完整代码
#include<bits/stdc++.h>
using namespace std;
#define N 100010
vector<int>f[N];
int n,a,b;
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>a>>b;
if(b==1) cout<<i<<endl;
f[b].push_back(i);
}
for(int i=1;i<=n;i++){
if(f[i].size()>1){
cout<<f[i][0]<<' '<<f[i][1]<<endl;
break;
}
}
return 0;
}