codeforces 734E(DFS,树的直径(最长路))

题目链接:http://codeforces.com/contest/734/problem/E

题意:有一棵黑白树,每次操作可以使一个同色连通块变色,问最少几次操作能使树变成全黑或全白。

思路:先进行缩点,同色连通块当作一点,用dfs实现并得到新图。答案即为(最长直径+1)/2。

关于最长直径的求法:http://www.cnblogs.com/*qi/archive/2012/04/08/2437424.html

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N = 2e5 + 5;
 5 int col[N],refl[N],maxdis,maxpos;
 6 vector <int> G[N],E[N];
 7 bool vis[N];
 8 void dfs(int x,int cur)
 9 {
10     if(vis[x])
11         return;
12     vis[x] = 1;
13     if(col[x] != col[cur])
14     {
15         E[x].push_back(cur);
16         E[cur].push_back(x);
17         cur = x;
18     }
19     for(int i = 0; i < G[x].size(); i++)
20         dfs(G[x][i],cur);
21 }
22 void DFS(int x,int dis)
23 {
24     if(vis[x])
25         return;
26     vis[x] = 1;
27     if(dis > maxdis)
28     {
29         maxdis = dis;
30         maxpos = x;
31     }
32     for(int i = 0; i < E[x].size(); i++)
33         DFS(E[x][i],dis + 1);
34 }
35 int main()
36 {
37     int n;
38     scanf("%d",&n);
39     for(int i = 1; i <= n; i++)
40         scanf("%d",col + i);
41     for(int i = 1; i <= n - 1; i++)
42     {
43         int u,v;
44         scanf("%d %d",&u,&v);
45         G[u].push_back(v);
46         G[v].push_back(u);
47     }
48     dfs(1,1);
49     memset(vis,0,sizeof(vis));
50     DFS(1,0);
51     memset(vis,0,sizeof(vis));
52     DFS(maxpos,0);
53     printf("%d
",(maxdis + 1) >> 1);
54     return 0;
55 }