题目
思路
最后差一点
首先发现黑色连通块显然不用去,删掉
然后所有叶子都是白色了
发现可以选择一条链走一次,剩下边都是两次
假设没有这条链 走完所有点
n
n
n 会花费
2
∗
(
n
−
1
)
+
白
点
2*(n-1)+白点
2∗(n−1)+白点 的代价
此时白点是往返后仍然为白点的点
再考虑链的情况
选择一段往返,那么会使得[起点+中间点]变色
白色变为黑色,少走一次+少按一下,代价-2
黑色变白色,少走一次但会多按一下
那么找覆盖最多白点的链即可
总代价:
2
(
n
−
1
)
−
2
∗
w
2(n-1)-2*w
2(n−1)−2∗w
代码
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<climits>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
int read(){
int f=0,x=0;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return !f?x:-x;
}
#define mp make_pair
const int MAXN=100000;
vector<int> G[MAXN+5];
int n;
char str[MAXN+5];
int whi[MAXN+5],sw[MAXN+5],de[MAXN+5],f[MAXN+5],del;
void DFS1(int u,int fa){
sw[u]=whi[u];
for(int i=0;i<(int)G[u].size();i++){
int v=G[u][i];
if(v==fa) continue;
DFS1(v,u),sw[u]+=sw[v];
}
return ;
}
void DFS2(int u,int fa){
f[u]=whi[u];
for(int i=0;i<(int)G[u].size();i++){
int v=G[u][i];
if(v==fa||!sw[v]) continue;
DFS2(v,u);
del=max(del,f[u]+f[v]);
f[u]=max(f[u],f[v]+whi[u]);
}
return ;
}
int main(){
n=read();
for(int i=1;i<n;i++){
int u=read(),v=read();
G[u].push_back(v);
G[v].push_back(u);
}
scanf("%s",str+1);
int rt=-1;
for(int i=1;i<=n;i++){
whi[i]=(str[i]=='W'?1:0);
if(whi[i])rt=i;
}
if(rt==-1){
puts("0");
return 0;
}
DFS1(rt,0);
int ans=0,cnt=0;
for(int u=1;u<=n;u++)
if(sw[u]){
for(int i=0;i<(int)G[u].size();i++){
int v=G[u][i];
if(sw[v]) de[u]++;
}
cnt++;
whi[u]^=(de[u]&1);
ans+=whi[u];
}
ans+=2*(cnt-1);
DFS2(rt,0);
ans-=2*del;
printf("%d\n",ans);
return 0;
}