专栏文章
P5628 【AFOI-19】面基
P5628题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minlyzex
- 此快照首次捕获于
- 2025/12/02 04:35 3 个月前
- 此快照最后确认于
- 2025/12/02 04:35 3 个月前
不是哥们,这题有什么好容斥的?直接换根啊!
观察到 很小,设计 表示子树 中距 为 的边的贡献总和。一个 dfs 可以快速解决。
我们应该要解决以每个点为根的答案的 。
对于以 为根的树,答案应为 ,然后枚举所有 ,先在 中减去 的贡献,同时更新子树大小,然后再在 中加入 。
代码很少很清晰。
CPP#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pb push_back
#define eb emplace_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll MOD=1e9+7;
// head
const int N=3e4+5,M=205;
int n,k;
vector<vector<int>> G(N);
int sz[N],f[N][M];
void dfs(int u,int fa)
{
sz[u]=1;
for(auto v:G[u]){
if(v==fa) continue;
dfs(v,u);
sz[u]+=sz[v];
for(int i=1;i<=k;i++) f[u][i]+=f[v][i-1];
f[u][0]+=sz[v]*(n-sz[v]);
}
}
int ans;
void dfs2(int u,int fa)
{
int sum=0;
for(int i=0;i<=k;i++) sum+=f[u][i];
ans=max(ans,sum);
for(auto v:G[u]){
if(v==fa) continue;
for(int i=1;i<=k;i++) f[u][i]-=f[v][i-1];
f[u][0]-=sz[v]*(n-sz[v]);
sz[u]-=sz[v],sz[v]+=sz[u];
for(int i=1;i<=k;i++) f[v][i]+=f[u][i-1];
f[v][0]+=sz[u]*(n-sz[u]);
dfs2(v,u);
for(int i=1;i<=k;i++) f[v][i]-=f[u][i-1];
f[v][0]-=sz[u]*(n-sz[u]);
sz[v]-=sz[u],sz[u]+=sz[v];
for(int i=1;i<=k;i++) f[u][i]+=f[v][i-1];
f[u][0]+=sz[v]*(n-sz[v]);
}
}
signed main()
{
cin.tie(nullptr);
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=1;i<n;i++){
int u,v;cin>>u>>v;
G[u].pb(v);
G[v].pb(u);
}
dfs(1,0);
dfs2(1,0);
cout<<ans<<'\n';
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...