Codeforces 734E Anton and Tree (dfs缩点+树的直径)

来源:互联网 发布:java api中文文档 编辑:程序博客网 时间:2024/05/24 03:31


E. Anton and Tree
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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

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

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
Input
110 0 0 1 1 0 1 0 0 1 11 21 32 42 55 65 73 83 93 109 11
Output
2
Input
40 0 0 01 22 33 4
Output
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.


题目大意:


现在给你N个点的一棵树,每个点都有一个颜色(0/1),每一次操作可以使得一种颜色的某一个连通块反色(0->1/1->0);

问最少操作多少次使得整颗树变成一种颜色。


思路:因为每次改变颜色都能使同颜色的相邻点改变颜色,所以相邻且颜色相同的点可以缩成一点,重新建图,构成黑白相间的点的树,设树的直径(任意两点的最远距离)为d,因为每次改变颜色都会使它与相邻的点的颜色相同,所以取树的直径上的点操作,共有d+1个点,因为点是黑白相间的,所以最少取(d+1)/2个点,一些枝叶上的点都会在直径上的点改变颜色的时候改变成相同颜色。


这题跟http://blog.csdn.net/qq_34374664/article/details/64123893有点像,只不过缩点可能会两个点之间连好几次,book数组控制下就好了。。这个树,没有任何影响,直接保证不从根回去就行,那题是在一个矩阵里,每个点bfs一下,bfs策略是每个点把自己取反,这样就跟外面的一样了,每个点找一条最短的。。这题是一颗树,他的直径上肯定是最长的,每隔一个翻转一个,就好了。。。

#include <iostream>#include <cstdio>#include <vector>#include <cstring>#include <algorithm>using namespace std;const int maxn = 2e5 + 5;const int INF = 1e8;int id[maxn], book[maxn], color[maxn], s, ans;vector<int> v[maxn], edg[maxn];void dfs(int x, int f, int col, int cnt){    for(int i = 0; i < v[x].size(); i++)    {        int to = v[x][i];        if(to == f) continue;        if(color[to] == col)        {            if(!id[to])            {                id[to] = cnt;                dfs(to, x, col, cnt);            }        }        else if(id[to])        {//            cout << cnt << ' ' << id[to] << endl;            edg[cnt].push_back(id[to]);            edg[id[to]].push_back(cnt);        }    }}void solve(int x, int f, int len){    if(ans <= len)    {        ans = len;        s = x;    }    for(int i = 0; i < edg[x].size(); i++)    {        int to = edg[x][i];        if(to == f) continue;        solve(to, x, len+1);    }}int main(){    int n, x, y, cnt;    while(~scanf("%d", &n))    {        memset(id, 0, sizeof(id));        cnt = 1;        for(int i = 1; i <= n; i++) scanf("%d", &color[i]);        for(int i = 1; i < n; i++)        {            scanf("%d%d", &x, &y);            v[x].push_back(y);            v[y].push_back(x);        }        for(int i = 1; i <= n; i++)        {            if(!id[i])            {                id[i] = cnt;                dfs(i, -1, color[i], cnt);                cnt++;            }        }        ans = -1;        solve(1, -1, 0);        solve(s, -1, 0);        printf("%d\n", (ans+1)/2);    }    return 0;}


阅读全文
0 0
原创粉丝点击