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

题目链接: Anton and Tree

题意:给出一棵树由0和1构成,一次操作可以将树上一块相同的数字转换为另一个(0->1 , 1->0),求最少几次操作可以把这棵数转化为只有一个数字的一棵数。

题解:首先一次可以改变一片数字,那么进行缩点后就变成了每次改变一个点。缩完点后这棵数变成了一棵相邻节点不同,0和1相交叉的一棵树。然后一棵树的直径上就是

0 1 0 1 0 1 0 1 0

这种情况,相当于从中间开始操作,总共操作(L+1)/2次。关于其他的分支一定会在直径的改变过程中完成改变。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAX_N = 2e5+9;
 4 const long long INF = 1e9+8;
 5 typedef pair<int,int> P;
 6 int N,M,T;
 7 vector<P> V;
 8 int dir[MAX_N];
 9 int vec[MAX_N];
10 int father[MAX_N];
11 int vis[MAX_N];
12 vector<int> tran[MAX_N];
13 int start,deep;
14 void init(){
15     for(int i=0;i<MAX_N;i++){
16         dir[i] = i;
17         tran[i].clear();
18         vis[i] = 0;
19     }
20     V.clear();
21     start = -1;
22     deep = 0;
23 }
24 int find_f(int x){
25     if(x == dir[x]) return x;
26     return dir[x] = find_f(dir[x]);
27 }
28 void bfs(int pos,int deepth){
29     if(deepth > deep){
30         deep = deepth;
31         start = pos;
32         //cout<<"....."<<deepth<<endl;
33     }
34     vis[pos] = 1;
35     for(int i=0;i<tran[pos].size();i++){
36         if(!vis[tran[pos][i]]) bfs(tran[pos][i],deepth+1);
37     }
38     return ;
39 }
40 int main()
41 {
42     while(cin>>N){
43         init();
44        for(int i=1;i<=N;i++){
45             scanf("%d",&vec[i]);
46        }
47        for(int i=0;i<N-1;i++){
48             int a,b;
49             scanf("%d%d",&a,&b);
50             int fa = find_f(a);
51             int fb = find_f(b);
52             if(vec[fa] == vec[fb] ) dir[fb] = dir[fa];
53             else V.push_back(P(fa,fb));
54        }
55        for(int i=1;i<=N;i++){
56             father[i] = find_f(i);
57        }
58        for(int i=0;i<V.size();i++){
59             P p = V[i];
60             //cout<<father[p.first]<<"...."<<father[p.second]<<endl;
61             tran[father[p.first]].push_back(father[p.second]);
62             tran[father[p.second]].push_back(father[p.first]);
63             start = father[p.first];
64        }
65        if(start == -1) {
66             cout<<0<<endl;
67        }
68        else{
69             bfs(start,0);
70             deep = 0;
71             for(int i=0;i<=N;i++) vis[i] = 0;
72             bfs(start,0);
73             cout<<(deep+1)/2<<endl;
74        }
75 
76     }
77     return 0;
78 }
79 /*
80 
81 
82 */

 

posted @ 2018-07-11 15:43  会打架的程序员不是好客服  阅读(245)  评论(0编辑  收藏  举报