求思路证明/证伪
查看原帖
求思路证明/证伪
1296826
lcfollower楼主2025/7/31 13:25

RT,设 fi,jf_{i ,j} 为第 ii 层用了 jj 个节点的最大节点数量,先预处理第 ii 层总共的节点数量 layerilayer_i,然后暴力转移:

fi,j=j+maxk=0min(j,layeri1)fi1,kf_{i ,j} = j + \max\limits_{k = 0}^{\min (j ,layer_{i - 1})} f_{i - 1 ,k}

求证明/证伪:这样正确。

个人感觉是选择所有节点的父节点一定最优,这样不劣,所以是正确的?

然后经过一点优化就到了时空 O(n)\mathcal O(n),然而并没有用到单调栈优化,很奇怪,不知道为啥,还是数据过水?

顺带代码:


const int N = 5e5 + 10;
int n ,dep[N] ,layer[N] ,f[2][N] ,pre[2][N] ,ans;
vector <int> edge[N];

inline void dfs (int u ,int fath){
  dep[u] = dep[fath] + 1;
  layer[dep[u]] ++;
  for (int v : edge[u]) {
    if (v == fath) continue;
    dfs (v ,u);
  }  
} signed main() {
  n = read ();
  up (i ,1 ,n - 1) {
    int u = read () ,v = read ();
      edge[u].push_back (v) ; edge[v].push_back (u);
  }
  dfs (1 ,0);
//f[i][j]:在层 i 用了 j 个节点的最大数量。
  f[1][1] = 1;
  up (j ,1 ,layer[1]) pre[1][j] = 1; 
  up (i ,2 ,n) {
    up (j ,1 ,layer[i]) pre[i & 1][j] = f[i & 1][j] = 0;
    up (j ,1 ,layer[i]) {
      int mx = pre[(i & 1) ^ 1][min (layer[i - 1] ,j)];
      f[i & 1][j] = j + mx;
      pre[i & 1][j] = max (pre[i & 1][j - 1] ,f[i & 1][j]);
      ans = max (ans ,f[i & 1][j]);
    }
  } writeln (ans);
  return 0;
}
2025/7/31 13:25
加载中...