求 hack
查看原帖
求 hack
131591
蒟蒻君HJT泽渡透香楼主2023/7/29 20:34

思路是换根 dp,down 一次 up 一次求出每个点的取值范围,感觉很对

#include <bits/stdc++.h>
int n, k, ve[100005], p[100005];
int l[100005], r[100005], dep[100005], ans[100005];
int noot;
std::vector <int> vc[100005];
void dfs1(int x, int fa){
  for(auto v : vc[x]){
    if(v == fa) continue;
    dep[v] = dep[x] + 1;
    dfs1(v, x);
  }
  return ;
}
void dfs2(int x, int fa){
  for(auto v : vc[x]){
    if(v == fa) continue;
    dfs2(v, x);
    l[x] = std::max(l[x], l[v] - 1);
    r[x] = std::min(r[x], r[v] + 1);
  } 
  return ;
}
void dfs3(int x, int fa){
  if(x != 1){
    l[x] = std::max(l[x], l[fa] - 1);
    r[x] = std::min(r[x], r[fa] + 1);
  }
  for(auto v : vc[x]){
    if(v == fa) continue;
    dfs3(v, x);
  }
  return ;
}
void dfs4(int x, int fa){
  for(auto v : vc[x]){
    if(v == fa) continue;
    int nmsl = ans[x] - 1; nmsl = std::max(nmsl, l[v]);
    if((nmsl ^ dep[v]) % 2 == noot) ans[v] = nmsl;
    else ans[v] = nmsl + 1;
    if(ans[v] > r[v]){
      printf("No\n");
      exit(0);
    }
    dfs4(v, x);
  }
}
int main(){
  scanf("%d", &n);
  for(int i = 1; i <= n - 1; ++i){
    int x, y;
    scanf("%d%d", &x, &y);
    vc[x].push_back(y);
    vc[y].push_back(x);
  }
  for(int i = 1; i <= n; ++i) l[i] = -200000, r[i] = 200000;
  dfs1(1, 0);
  scanf("%d", &k);
  for(int i = 1; i <= k; ++i) scanf("%d%d", &ve[i], &p[i]);
  for(int i = 1; i <= k; ++i) l[ve[i]] = r[ve[i]] = p[i];
  for(int i = 2; i <= k; ++i){
    int s1 = dep[ve[i - 1]] + p[i - 1];
    int s2 = dep[ve[i]] + p[i];
    if(s1 % 2 != s2 % 2){
      printf("No\n");
      return 0;
    }
  }
  noot = (dep[ve[1]] ^ p[1]) % 2;
  dfs2(1, 0);
  dfs3(1, 0);
  for(int i = 1; i <= n; ++i)
    if(l[i] > r[i]){
      printf("No\n");
      return 0;
    }
  printf("Yes\n");
  if(l[1] % 2 == noot) ans[1] = l[1];
  else ans[1] = l[1] + 1;
  if(ans[1] > r[1]){
    printf("No\n");
    return 0;
  }
  dfs4(1, 0);
  for(int i = 1; i <= n; ++i) printf("%d\n", ans[i]);
  return 0;
}
2023/7/29 20:34
加载中...