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;
}