CodeForces 734 E.Anton and Tree

E. Anton and Tree

time limit per test 3 seconds
memory limit per test 256 megabytes

Anton is growing a tree in his garden. In case you forgot, the tree is a connected acyclic undirected graph.

There are n vertices in the tree, each of them is painted black or white. Anton doesn’t like multicolored trees, so he wants to change the tree such that all vertices have the same color (black or white).

To change the colors Anton can use only operations of one type. We denote it as paint(v), where v is some vertex of the tree. This operation changes the color of all vertices u such that all vertices on the shortest path from v to u have the same color (including v and u). For example, consider the tree

p1

and apply operation paint(3) to get the following:

p2

Anton is interested in the minimum number of operation he needs to perform in order to make the colors of all vertices equal.

Input
The first line of the input contains a single integer n (1 ≤ n ≤ 200 000) — the number of vertices in the tree.
The second line contains n integers colori (0 ≤ colori ≤ 1) — colors of the vertices. colori = 0 means that the i-th vertex is initially painted white, while colori = 1 means it’s initially painted black.
Then follow n - 1 line, each of them contains a pair of integers ui and vi (1 ≤ ui, vi ≤ n, ui ≠ vi) — indices of vertices connected by the corresponding edge. It’s guaranteed that all pairs (ui, vi) are distinct, i.e. there are no multiple edges.

Output
Print one integer — the minimum number of operations Anton has to apply in order to make all vertices of the tree black or all vertices of the tree white.

Examples
input1

11
0 0 0 1 1 0 1 0 0 1 1
1 2
1 3
2 4
2 5
5 6
5 7
3 8
3 9
3 10
9 11

output1

2

input2

4
0 0 0 0
1 2
2 3
3 4

output2

0

Note
In the first sample, the tree is the same as on the picture. If we first apply operation paint(3) and then apply paint(6), the tree will become completely black, so the answer is 2.
In the second sample, the tree is already white, so there is no need to apply any operations and the answer is 0.

Solution

我们可以先缩点(把一块同色的联通块看做一个点),容易发现:直径上的点总是变的最慢的,所以最小的次数为 l e n g t h ( d i a . ) / 2

缩点可以有很多种方式,这里介绍一种,每次找最近的与自己颜色不同的后代,然后加边

p3

缩点之后,变成了

这里写图片描述

可以发现树上的任意一条链都是黑白交替的

Code

#include <cstdio>
#define N 4000005
using namespace std;

struct Node{
    int to, nxt;
}e1[N], e2[N];
int po1, po2, lst1[N], lst2[N], cnt1, cnt2, a[N], d[N];

inline void add1(int u, int v) {
    e1[++cnt1].to = v;
    e1[cnt1].nxt = lst1[u];
    lst1[u] = cnt1;
}

inline void add2(int u, int v) {
    e2[++cnt2].to = v;
    e2[cnt2].nxt = lst2[u];
    lst2[u] = cnt2;
}

void dfs(int x, int co, int fa, int fafa) {
    for (int i = lst1[x]; i; i = e1[i].nxt) {
        if (e1[i].to == fa) continue;
        if (a[e1[i].to] == co) {
            add2(e1[i].to, fafa);
            add2(fafa, e1[i].to);
            dfs(e1[i].to, 1 - co, x, e1[i].to);
        }
        else dfs(e1[i].to, co, x, fafa);
    }
}

void dfs1(int x, int fa) {
    d[x] = d[fa] + 1;
    if (d[x] > d[po1]) po1 = x;
    for (int i = lst2[x]; i; i = e2[i].nxt) {
        if (e2[i].to == fa) continue;
        dfs1(e2[i].to, x);
    }
}

void dfs2(int x, int fa) {
    d[x] = d[fa] + 1;
    if (d[x] > d[po2]) po2 = x;
    for (int i = lst2[x]; i; i = e2[i].nxt) {
        if (e2[i].to == fa) continue;
        dfs2(e2[i].to, x);
    }
}

int main() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    for (int i = 1; i < n; ++i) {
        int x, y;
        scanf("%d%d", &x, &y);
        add1(x, y);
        add1(y, x);
    }
    dfs(1, 1 - a[1], 1, 1);//缩点
    po1 = 1;
    dfs1(1, 1);//求直径
    po2 = po1;
    d[po1] = 0;
    dfs2(po1, po1);//求直径
    printf("%d\n", d[po2] / 2);
    return 0;
}

如果有不会求直径的小盆友,戳这里_来自qianguch

猜你喜欢

转载自blog.csdn.net/jokingcoder/article/details/81384553
今日推荐