AT_arc097_d [ARC097F] Monochrome Cat

Solution

一道模拟赛的 T3,好不容易做出来结果 T1 爆 0 了。

\(\texttt{W}\) 的值为 \(1\)\(\texttt{B}\) 的值为 \(0\)。转化为将所有的点变为 \(0\)

考虑起点和终点在同一个点的情况,肯定需要将所有为 \(w_i=1\) 的点都遍历一遍。先去掉所有点均为 \(0\) 的子树,若要进去答案肯定不优。此时会形成一个叶子均为 \(1\) 的新树。

会有每个点被进入的次数为它的度数。设 \(E\) 为新树的边集,第 \(i\) 个点的度数为 \(d_i\)。此时的答案为 \(|E|\times 2+\sum w_i\oplus (d_i \& 1)\)。即如果 \(i\) 被进入奇数次,那它的权值就会改变。

\(w_i\) 更改为 \(w_i\oplus (d_i\&1)\)

若起点和终点不相同,那么会有从起点到终点的路径除了终点以外的点的权值均会改变。设路径长为 \(L\),除了终点的点集为 \(V\),有 \(L=|V|\)。那么答案会减少 \(L+\sum\limits_{i\in V} [w_i=1]-\sum\limits_{i\in V} [w_i=0]=\sum\limits_{i\in V} [w_i=1]\times (1+1)-\sum\limits_{i\in V} [w_i=0]\times (1-1)=2\times\sum\limits_{i\in V} [w_i=1]\)

因此需要求 \(\sum\limits_{i\in V} [w_i=1]\) 最大的路径。

会发现端点的值一定为 \(0\),因此不用考虑终点的值。设 \(h_i\) 表示 \(i\) 到子树的最大的权值, \(g_i\) 表示经过 \(i\) 的链的权值最大值。树形 dp 即可。

注意: 要特判只有一个点为 \(1\) 的情况,此时答案为 \(1\),不判可能会输出 \(-1\)

Code

#include<bits/stdc++.h>
#define IOS cin.tie(0),cout.tie(0),ios::sync_with_stdio(0)
#define ll long long
#define db double
#define pb push_back
#define eb emplace_back
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define PLL pair<ll,ll>
#define PII pair<int,int>
#define Tp template<typename T>
#define Ts template<typename T,typename ...args>
Tp inline T lb(T x){return x&-x;}
using namespace std;
const int N=1e5+20,M=1e5+20;
const ll INF=1ll<<60,mod=998244353;
namespace H_H{
	int n,rt=1,f[N],sum_w,E;
	vector<int> to[N],to1[N];
	bool w[N],in[N];
	inline void dfs1(int u,int fa){
		if(w[u]) f[u]=1;
		for(int v:to[u]){
			if(v==fa) continue;
			dfs1(v,u);
			f[u]+=f[v];
		}
		in[u]=f[u] && (sum_w-f[u] || w[u]);
	}
	inline void solve1(){//求新树
		dfs1(rt,0);
		for(int i=1;i<=n;i++){
			if(!in[i]) continue;
			for(int v:to[i]) if(in[v]) to1[i].pb(v),E++;
		}
		swap(to,to1);
		sum_w=0;
		for(int i=1;i<=n;i++){
			if(!in[i]) continue;
			w[i]^=(int)to[i].size()&1;
			sum_w+=w[i];
		}
	}
	int g[N],h[N];
	inline void dfs2(int u,int fa){//树形 dp
		int mx1=0,mx2=0;//维护最大和次大值
		for(int v:to[u]){
			if(v==fa) continue;
			dfs2(v,u);
			h[u]=max(h[u],h[v]);
			if(h[v]>mx1) mx2=mx1,mx1=h[v];
			else mx2=max(mx2,h[v]); 
		}
		h[u]+=w[u];g[u]=mx1+mx2+w[u];
	}
	inline ll calc(){
		dfs2(rt,0);
		int ans=0;
		for(int i=1;i<=n;i++){
			if(in[i]) ans=max(ans,g[i]);
		}
		if(E+sum_w==1) return 1;
		return E+sum_w-ans*2;
	}
	int main(){
		cin>>n;
		for(int i=1,u,v;i<n;i++){
			cin>>u>>v;
			to[u].pb(v);
			to[v].pb(u);
		}
		for(int i=1;i<=n;i++){
			char ch;cin>>ch;
			sum_w+=(w[i]=ch=='W');
			if(w[i]) rt=i;
		}
		solve1();
		cout<<calc()<<"\n";
		return 0;
	}
}
int main(){
	IOS;H_H::main();
	return 0;
}
posted @ 2025-11-30 16:19  tyh_27  阅读(1)  评论(0)    收藏  举报