题意:给你一棵树, 每个点要么是黑色要么是白色, 有一种操作是将同一个颜色的连通块变成相反的颜色,问你最少变换几次, 整颗树变成一种颜色。
思路: 缩点, 加求树的直径, 答案为树的直径除二向上取整。
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define mk make_pair 4 using namespace std; 5 6 const int N = 5e5 + 7; 7 const int inf = 0x3f3f3f3f; 8 const int INF = 0x3f3f3f3f3f3f3f3f; 9 10 int n, a[N], cnt[N], tot, vis[N], depth[N], id, ans; 11 vector<int> edge1[N], edge2[N]; 12 13 void dfs(int u, int pre, int op, int f) { 14 vis[u] = f; 15 for(int v : edge1[u]) { 16 if(v == pre || a[v] != op) 17 continue; 18 dfs(v, u, op, f); 19 } 20 } 21 22 void dfs2(int u, int pre, int deep) { 23 depth[u] = deep; 24 if(depth[u] > depth[id]) 25 id = u; 26 for(int v : edge2[u]) { 27 if(v == pre) continue; 28 dfs2(v, u, deep + 1); 29 } 30 } 31 32 void dfs3(int u, int pre, int deep) { 33 ans = max(ans, deep); 34 for(int v : edge2[u]) { 35 if(v == pre) continue; 36 dfs3(v, u, deep + 1); 37 } 38 } 39 int main() { 40 scanf("%d", &n); 41 for(int i = 1; i <= n; i++) { 42 scanf("%d", &a[i]); 43 } 44 45 for(int i = 1; i < n; i++) { 46 int u, v; scanf("%d%d", &u, &v); 47 edge1[u].push_back(v); 48 edge1[v].push_back(u); 49 } 50 51 for(int i = 1; i <= n; i++) { 52 if(vis[i]) continue; 53 dfs(i, 0, a[i], ++tot); 54 } 55 56 for(int u = 1; u <= n; u++) { 57 for(int v : edge1[u]) { 58 if(u > v || vis[u] == vis[v]) 59 continue; 60 edge2[vis[u]].push_back(vis[v]); 61 edge2[vis[v]].push_back(vis[u]); 62 } 63 } 64 65 dfs2(1, 0, 0); 66 dfs3(id, 0, 0); 67 if(ans & 1) ans++; 68 printf("%d\n", ans / 2); 69 return 0; 70 } 71 /* 72 */
原文地址:https://www.cnblogs.com/CJLHY/p/8873877.html
时间: 2024-11-04 12:30:04