[ICPC 2026 NAC] Acorn Quarrels
[ICPC 2026 NAC] Acorn Quarrels
我们要让初始状态和目标状态相同,这很困难。
考虑更严的限制,我们要让每条边都恰好来回运输 \(1\) 次,这样必然能够保证不变。
此时在松鼠 \(x\) 操作时,\(x\) 的邻居必然全部相等,我们设此时 \(x\) 的邻居均为 \(f_x\)。
考虑 \(x\) 的邻居 \(y\),从 \(x\) 的角度考虑,在轮到 \(x\) 偷时 \(y\) 会被偷 \(t_{x,y}\) 次,其中 \(t_{x,y}\) 表示 \(y\) 的邻居中比 \(x\) 编号小的个数。同时若 \(x > y\),则 \(y\) 会获得 \(g_y\) 的橡果,此为 \(y\) 的度数,也即其可偷的总数,可得:
\[f_x = d_y - t_{x,y} + [x > y] g_y
\]
同时还有:
\[d_x = f_y + t_{y,x} - [y > x] g_x
\]
递归计算即可,这里我们先钦定 \(d_1 = f_1 = 0\),遍历后奇数偶数层独立,归到对应值域。
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
map<int,long long> t[100010];
long long g[100010],f[100010],d[100010],depth[100010];
vector<int> G[100010];
void dfs(int u,int fa,int cur){
depth[u]=cur;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v!=fa){
f[v]=d[u]-t[v][u];
if(v>u){
f[v]+=g[u];
}
d[v]=f[u]+t[u][v];
if(u>v){
d[v]-=g[v];
}
dfs(v,u,cur+1);
}
}
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<n;i++){
int u,v;
scanf("%d %d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
g[u]++;
g[v]++;
}
for(int u=1;u<=n;u++){
sort(G[u].begin(),G[u].end());
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
t[v][u]=i;
}
}
dfs(1,-1,1);
long long minn0=0x3f3f3f3f3f3f3f3f,minn1=0x3f3f3f3f3f3f3f3f;
for(int i=1;i<=n;i++){
if(depth[i]%2==0){
minn0=min(minn0,d[i]);
}
else{
minn1=min(minn1,d[i]);
}
}
for(int i=1;i<=n;i++){
if(depth[i]%2==0){
d[i]=d[i]-minn0+n;
}
else{
d[i]=d[i]-minn1+n;
}
printf("%lld ",d[i]);
}
return 0;
}

浙公网安备 33010602011771号