http://codeforces.com/contest/1143/problem/C
反着考虑 考虑对立事件即孝顺的留下来
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<set>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1000000;
int vis[maxn];
int a[maxn];
set<int>s;
int main(){
int t;
cin>>t;
int p=0;
for(int i=1;i<=t;i++){
int x,y;
cin>>x>>y;
if(x==-1){
p=i;
vis[i]=1;//父节点不被删
}
else{
if(y==0){//只要该结点孝顺 该结点和父节点一定不被删 及时父节点本来不孝顺
vis[x]=1;
vis[i]=1;
}
}
}
for(int i=1;i<=t;i++){
if(!vis[i]){
s.insert(i);
}
}
if(s.size()==0) cout<<"-1"<<endl;
else{
set<int> :: iterator it;
for(it=s.begin();it!=s.end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
return 0;
}
dfs写法 原理一样
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<vector>
#include<set>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1000000;
vector<int> v[maxn];
set<int>s;
int a[maxn];
void dfs(int x){
int len=v[x].size();
if(len==0) return ;
for(int i=0;i<len;i++){
a[x]=a[x]&a[v[x][i]];//要是&后为1 则该点必删 负责不删
dfs(v[x][i]);
}
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
v[i].clear();
}
int p=0;
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
if(x==-1){
p=i;
a[p]=0;
}else{
v[x].push_back(i);
a[i]=y;
}
}
dfs(p);
a[p]=0;
for(int i=1;i<=n;i++){
if(a[i]){
s.insert(i);
}
}
if(s.size()==0) cout<<"-1"<<endl;
set<int>:: iterator it;
for(it=s.begin();it!=s.end();it++){
cout<<*it<<" ";
}
}