AT4133 [ARC097D] Monochrome Cat

题链

分析

显然只需要处理白点的最小联通块
显然每条边至多走2次
显然只会有一条路径走1次
显然每个点的贡献是已知的,树形DP即可,注意链的末尾不被统计

#include<bits/stdc++.h>
#define pb push_back
const int INF=1e9;
using namespace std;
const int N=1e5+5;
int n,rt,a[N],b[N],f0[N],f1[N],f2[N],g0[N],g1[N],g2[N];
vector<int>V[N];
namespace tree {
	vector<int>V[N];
	char co[N];
	void dfs(int fa,int u) {
		if(co[u]=='W') a[u]=1,b[u]++;
		for(int v:V[u]) {
			if(v!=fa){
				dfs(u,v);
				b[u]+=b[v];
			}
		}
	}
	void init() {
		scanf("%d",&n);
		for(int i=1;i<n;i++) {
			int u,v; scanf("%d%d",&u,&v);
			V[u].pb(v),V[v].pb(u);
		}
		scanf("%s",co+1); rt=0;
		for(int i=1;i<=n;i++) {
			if(co[i]=='W') {
				rt=i; break;
			}
		}
		if(!rt) {
			puts("0"); exit(0);
		}
		dfs(0,rt); 
	}
}
int ask(int fa,int u) {
	int ret=0; 
	for(int v:V[u]) {
		if(v!=fa) {
			ret=max(ret,ask(u,v));
			if(f1[v]>=f1[u]) {
				f2[u]=f1[u];
				f1[u]=f1[v];
				f0[u]=v;
			} else f2[u]=max(f2[u],f1[v]);
			if(g1[v]>=g1[u]) {
				g2[u]=g1[u];
				g1[u]=g1[v];
				g0[u]=v;
			} else g2[u]=max(g2[u],g1[v]);
		}
	}
	if(!g0[u]) {
		g1[u]=0;
		if(a[u]) f1[u]=2; else f1[u]=0;
		return ret;
	}
	if(a[u]) g1[u]+=2,g2[u]+=2;
	if(f0[u]!=g0[u]) ret=max(rt,g1[u]+f1[u]);
		else ret=max(ret,max(g1[u]+f2[u],g2[u]+f1[u]));
	if(a[u]) f1[u]+=2;
	return ret;
}
int main() {
	tree::init(); int ans=0;
	for(int i=1;i<=n;i++) {
		if(b[i]) {
			for(int v:tree::V[i]) {
				if(b[v]) V[i].pb(v),ans++;
			}
		}
	}
	for(int i=1;i<=n;i++) {
		a[i]^=V[i].size()&1,ans+=a[i];
	}
	cout<<ans-ask(0,rt)<<endl;
	return 0;
}
posted @ 2021-06-11 23:08  wwwsfff  阅读(40)  评论(0编辑  收藏  举报