[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;
}
posted @ 2026-07-14 16:52  Oken喵~  阅读(35)  评论(0)    收藏  举报