http://codeforces.com/contest/734/problem/E
http://codeforces.com/blog/entry/48397
打CF,才知道自己和世界玩ACM的人的差距。
当然了,只要是打比赛,都知道。
——
这题题意是
一棵树,每个点有黑白两色,每一次染色,可以把这一片和周围其它和它相同的颜色变色,问搞几次变成同一种颜色。
——
比赛的时候我居然想的是要么白的全变黑,要么黑的全变白,DFS,真是Naive
——
实际上应该可以黑变白,白再变黑,这样可能次数更少
——
算法第一步首先压缩图形,把相同颜色且相连的点变成一个点。这样显然不改变ANS。
那么图肯定是一个一黑一白一黑一白交错相连的树
那么最佳方案肯定是从最中心的那个点开始变色,每次变成和旁边的点的颜色相同,这样就可以压缩,然后再变
ans = (d + 1) / 2 d为树上最长两个点的距离
我们当然可以枚举每一个点DFS把这个d给找出来
不过题解给了一个更为优化的方法,并且大多数人都是这么写的,莫非这是一个经典的问题?
well-known问题
不过我也不得而知了
这个优化算法是
从根开始往下走,每到一个点,不往回走了
继续往下走,那么肯定可以找到以这个点为根的最大距离,但是最长距离可能不包括根
不过肯定是以这个点为根的最大距离和第二大距离之和
——
#define LOG(x) cout << #x << " = " << (x) << endl
#define PRINTLN(x) cout << (x) << endl
#define MEM(x, y) memset((x), (y), sizeof((x)))
#include <bits/stdc++.h>
using namespace std;
const double PI = 2*acos(0);
typedef long long ll;
typedef complex<double> Complex;
int nextInt()
{
int x;
scanf("%d", &x);
return x;
}
ll nextLL()
{
ll x;
scanf("%lld", &x);
return x;
}
//TEMPLATE
//MAIN
const int MAXN = 200000;
int color[MAXN];
vector<int> g[MAXN];
bool vis[MAXN];
int lv[MAXN];
vector<int> g1[MAXN];
int n;
void dfs(int u, int c, int l)
{
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i];
if (vis[v] || color[v] != c) continue;
vis[v] = true;
lv[v] = l;
dfs(v, c, l);
}
}
int ans;
int dfs1(int u, int p) // p is parent
{
int max1 = 0, max2 = 0;
for (int i = 0; i < g1[u].size(); i++) {
int v = g1[u][i];
if (v == p) continue;
max2 = max(max2, dfs1(v, u) + 1);
if (max1 < max2) swap(max1, max2);
}
ans = max(ans, max1 + max2);
return max1;
}
void solve()
{
for (int i = 0; i < n; i++) {
color[i] = nextInt();
g[i].clear();
g1[i].clear();
}
for (int i = 0; i < n - 1; i++) {
int u = nextInt() - 1, v = nextInt() - 1;
g[u].push_back(v);
g[v].push_back(u);
}
MEM(vis, false);
int l = 0;
for (int i = 0; i < n; i++) {
if (!vis[i]) {
vis[i] = true;
lv[i] = l;
dfs(i, color[i], l++);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < g[i].size(); j++) {
int v = g[i][j];
if (lv[i] != lv[v]) {
g1[lv[i]].push_back(lv[v]);
}
}
}
ans = 0;
dfs1(0, -1);
cout << (ans + 1) / 2 << endl;
}
int main()
{
//freopen("in.txt", "r", stdin);
while (scanf("%d", &n) != EOF) {
solve();
}
}