描述
小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
当时没做出来,想的太复杂了,本题最重要的条件应该是N个结点,N条边的树,任意一棵n个结点的树的边树都是n-1.
只要发现这一点就不难发现这题的做法,就是一个结点在y上出现了两次时,肯定这一行有错。此时任意去掉一条边即可。
还有一种情况就是1为根节点,即1为第二列时选中。
代码:
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
int x[100001],y[100001];
int main(){
freopen("E:\input.txt","r",stdin);
int n;
cin>>n;
map<int,int> hashx,hashy;
for(int i=0;i<n;i++){
cin>>x[i]>>y[i];
++hashy[y[i]];
}
set<int> ans;
for(int i=0;i<n;i++){
if(y[i]==1) ans.insert(i+1);
else{
if(hashy[y[i]]>=2) ans.insert(i+1);
}
}
for(auto i=ans.begin();i!=ans.end();i++){
if(i!=ans.begin()) cout<<" ";
cout<<*i;
}
}