题意:
分析:
对于这个树形结构的关系网络,不难发现一个trick:如果U比V先离开且满足题意,那么以V为根U的子树都一定不会是最后一个离开的,如果想让U的子树中的某一个最后离开,那么U离开后必然会分割成两个联通块,最后一定不会满足条件
先随便找一个根dfs出树形结构,(1)如果V不在U的子树中,直接差分标记【st[u],ed[u]】;(2)如果V在U的子树中,需要先找到U--->V路径上的第二个节点son,差分标记【st[1],st[son]-1】和【ed[son]+1,ed[1]】即可,找这个son节点,可以用类似找LCA的方法倍增找到,也可以用vector存下每个节点的儿子节点,暴力判断即可
对于每一个条件,连一条有向边U--->V,如果成环那么每个点都不可能最后离开,有向图判环拓扑排序即可
代码:
#include <bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int maxn = 1e5+15;
inline int read() {
int x = 0, f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
return x * f;
}
int n,m,u,v,cnt,cnt1,tim,head[maxn],head1[maxn];
int st[maxn],ed[maxn],id[maxn],flag[maxn],a[maxn],in[maxn],dp[maxn][20],deep[maxn];
struct edge{
int to,nxt;
}e[maxn<<1],e1[maxn<<1];
inline void add(int u,int v){
e[++cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
inline void add1(int u,int v){
e1[++cnt1].to = v;
e1[cnt1].nxt = head1[u];
head1[u] = cnt1;
}
void dfs(int u,int fa){
st[u] = ++tim;id[tim] = u;
for(int i = head[u]; i ;i = e[i].nxt){
int v = e[i].to;
if(fa == v) continue;
dp[v][0] = u;deep[v] = deep[u]+1;
dfs(v,u);
}
ed[u] = tim;
}
void init(int n)
{
for(int j=1;(1<<j)-1<=n;j++)
for(int i=1;i<=n;i++)
dp[i][j]=dp[dp[i][j-1]][j-1];
}
int LCA(int u,int v)
{
if(deep[u]<deep[v]) swap(u,v);
int h = deep[u]-deep[v]-1; //找最近公共祖先的儿子,所以减1
for(int i=0;i<=19;i++)
{
if(h&(1<<i))
u=dp[u][i];
}
return u;
}
inline void Tag(int l,int r){
if(l > r) return;
a[l]++; a[r+1]--;
}
void solve(int u,int v){
if(st[v] >= st[u] && ed[v] <= ed[u]){
int son = LCA(u,v);
Tag(st[1],st[son]-1);
Tag(ed[son]+1,ed[1]);
}
else Tag(st[u],ed[u]);
}
bool check(){ //判环
queue<int> q;
int sum = 0;
for(int i = 1;i <= n; ++i) if(!in[i]) q.push(i);
while(!q.empty()){
int u = q.front();q.pop();
sum++;
for(int i = head1[u]; i ;i = e1[i].nxt){
int v = e1[i].to;
if(--in[v] == 0) q.push(v);
}
}
return sum == n;
}
int main(){
n = read(),m = read();
for(int i = 1;i < n ;++i){
u = read(),v = read();
add(u,v);
add(v,u);
}
dfs(1,0);
init(n);
while(m--){
u = read(),v = read();
add1(u,v);
in[v]++;
solve(u,v);
}
if(!check()){
for(int i = 0;i < n; ++i) puts("0");
return 0;
}
for(int i = 1;i <= n; ++i){
a[i] += a[i-1];
if(!a[i]) flag[id[i]] = 1;
}
for(int i = 1;i <= n; ++i){
if(flag[i]) puts("1");
else puts("0");
}
return 0;
}