看到这道题我们自然而然地就会想到拓扑。但是拓扑的时候不能满足题目的第二个条件:必须满足奶牛 Ai 要比奶牛 Bi 先离开。那我们就先按照 M 行的数据建个单向边,然后等会刷拓扑的时候一起刷,这样就能保证 Ai 要先比 Bi 刷到,也就是先离开。等我们找到第一个入度为 0 的点时,我们就找到了树根。接下来我们从树根开始反推,比如限定条件的 (A,B) ,那么 A 所在的子树(包括 A )都必须先处理掉,因为这帮家伙都不可能最后删除,那么剩下的都是可零可一的节点。按照题目的要求,那么我们绝对要全给 1 啊。
```cpp
#include<bits/stdc++.h>
#define TT 200000
using namespace std;
const int maxn=100005,maxe=200005;
int n,m,fa,hed,til,tot[2],du[maxn],ans[maxn],que[maxe],son[2][maxe],lnk[2][maxn],nxt[2][maxe];
bool vis[maxn];
inline int read(){
int ret=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
void add_e(int k,int x,int y){du[y]++;son[k][++tot[k]]=y;nxt[k][tot[k]]=lnk[k][x];lnk[k][x]=tot[k];}
void Topu(){
for(int i=1;i<=n;i++)if(du[i]==1)que[++til]=i;
while(hed<=til){
hed=(hed+1)%TT;
if(du[que[hed]]==0){fa=que[hed];return ;}
for(int j=lnk[0][que[hed]];j;j=nxt[0][j])if(--du[son[0][j]]==1)que[til=(til+1)%TT]=son[0][j];
for(int j=lnk[1][que[hed]];j;j=nxt[1][j])if(--du[son[1][j]]==1)que[til=(til+1)%TT]=son[1][j];
}
}
void dfs(int x,int father){
ans[x]=1;
for(int j=lnk[0][x];j;j=nxt[0][j]){
if(son[0][j]==father||vis[son[0][j]])continue;
dfs(son[0][j],x);
}
}
int main(){
n=read();m=read();
for(int i=1;i<n;i++){
int x=read(),y=read();
add_e(0,x,y);add_e(0,y,x);
}//建双向边
for(int i=1;i<=m;i++){
int x=read(),y=read();
add_e(1,x,y);
vis[x]=1;
}//再建图
Topu();//找树根
dfs(fa,0);//从根上开始遍历
for(int i=1;i<=n;i++)printf("%d\n",ans[i]);//输出答案
return 0;
}
```