原题链接:https://arc097.contest.atcoder.jp/tasks/arc097_d
Monochrome Cat
Problem Statement
There is a tree with N vertices numbered 1 through N. The i-th edge connects Vertex xi and yi. Each vertex is painted white or black. The initial color of Vertex i is represented by a letter ci. ci = W represents the vertex is white; ci = B represents the vertex is black.
A cat will walk along this tree. More specifically, she performs one of the following in one second repeatedly:
Choose a vertex that is adjacent to the vertex where she is currently, and move to that vertex. Then, invert the color of the destination vertex.
Invert the color of the vertex where she is currently.
The cat’s objective is to paint all the vertices black. She may start and end performing actions at any vertex. At least how many seconds does it takes for the cat to achieve her objective?
Constraints
1 ≤ N ≤ 105
1 ≤ xi,yi ≤ N (1 ≤ i ≤ N−1)
The given graph is a tree.
ci = W or ci = B.
Input
Input is given from Standard Input in the following format:
N
x1 y1
x2 y2
:
xN−1 yN−1
c1c2..cN
Output
Print the minimum number of seconds required to achieve the objective.
Sample Input 1
5
1 2
2 3
2 4
4 5
WBBWW
Sample Output 1
5
The objective can be achieved in five seconds, for example, as follows:
Start at Vertex 1. Change the color of Vertex 1 to black.
Move to Vertex 2, then change the color of Vertex 2 to white.
Change the color of Vertex 2 to black.
Move to Vertex 4, then change the color of Vertex 4 to black.
Move to Vertex 5, then change the color of Vertex 5 to black.
Sample Input 2
6
3 1
4 5
2 6
6 1
3 4
WWBWBB
Sample Output 2
7
Sample Input 3
1
B
Sample Output 3
0
Sample Input 4
20
2 19
5 13
6 4
15 6
12 19
13 19
3 11
8 3
3 20
16 13
7 14
3 17
7 8
10 20
11 9
8 18
8 2
10 1
6 13
WBWBWBBWWWBBWWBBBBBW
Sample Output 4
21
题目大意
给定一棵有n个节点的树,每个点有黑白两个颜色。现在有一只猫可以从任意节点开始,任意一个节点结束,要把所有节点染成黑色。
可以执行如下两种操作之一:
1.移动到相邻节点,并改变其颜色;
2.改变当前节点颜色;
求:把所有节点染成黑色所需的最少操作次数
数据范围:N<=2e5
题解
首先,显然的是,对于一个全黑的子树,我们肯定是不会访问的,那不如将所有的全黑子树砍掉,这样,叶子节点必定是白色。
考虑一个简单的情况:起点和终点是一样的,那么,我们肯定要从白点出发,遍历整棵树,回到起点,形成一个欧拉回路,整个过程的代价由每个点的度数和本身颜色决定,可以 O(n) O ( n ) 直接计算,首先每条边要被经过两次, 总权值+=每个点的度数 总 权 值 + = 每 个 点 的 度 数 ,另外,当 点度+颜色(白色为0,黑色为1) mod 2=0 点 度 + 颜 色 ( 白 色 为 0 , 黑 色 为 1 ) m o d 2 = 0 时,还需要多花一个单位的代价。
那么,起点和终点不一样呢?
由于叶子节点都是白色,所以每个叶子节点都要被到达一次,那么我们的终点肯定也是一个叶子节点。这样,我们的实际路径就是欧拉回路减去了起点到终点的一条链。
对于起点到终点的链,除了终点,其他点都被少到达了一次,即颜色少改变了一次。那么,在原来欧拉回路遍历时可以直接变成黑色的点,虽然被少到达了一次,但同时也要花一个单位的代价多改一次颜色,没有减少代价;而原来遍历完是白色的点,不仅少到达了一次,还不需要花额外的代价更改颜色,减少了2个单位代价。于是,我们可以赋权后做树形 dp d p 。
因为上面的讨论没有考虑终点,所以在 dp d p 时,我们为了给终点留个位置,要维护两个值,一个是该点到叶子节点的路径中权值最大的,另一个是该点到一个叶子节点爸爸的路径中权值最大的。减少的代价,就是一条包含叶子节点的路径加上一条不包含叶子节点的路径不断取 max m a x 即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
vector<int>mmp[M];
int col[M],du[M],val[M],dp1[M],dp2[M],n,rt,tot,more;
bool allb[M];
char ch[M];
void in()
{
int a,b;
scanf("%d",&n);
for(int i=1;i<n;++i)
scanf("%d%d",&a,&b),mmp[a].push_back(b),mmp[b].push_back(a);
scanf("%s",ch+1);
for(int i=1;i<=n;++i)col[i]=ch[i]=='W'?0:1,rt=col[i]?rt:i;
}
void dfs(int v,int f)
{
allb[v]=col[v];int to;
for(int i=mmp[v].size()-1;i>=0;--i)
{
to=mmp[v][i];if(to==f)continue;
dfs(to,v);
if(!allb[to])++du[v],++du[to];
allb[v]&=allb[to];
}
}
void dp(int v,int f)
{
tot+=du[v];
if((du[v]+col[v])&1)val[v]=0;
else val[v]=2,++tot;
int mx1=0,mx2=0,to;bool flag=0;
for(int i=mmp[v].size()-1;i>=0;--i)
{
to=mmp[v][i];if(to==f||allb[to])continue;
flag=1;dp(to,v);
more=max(more,max(dp1[to]+mx2+val[v],dp2[to]+mx1+val[v]));
mx1=max(dp1[to],mx1);mx2=max(dp2[to],mx2);
}
dp1[v]=mx1+val[v];dp2[v]=flag?mx2+val[v]:-INT_MAX;
}
void ac()
{
dfs(rt,0);dp(rt,0);
if(rt)printf("%d",tot-more);
else printf("0");
}
int main()
{
in();ac();
return 0;
}