传送门:>Here<

题意:给出一颗树,节点不是黑色就是白色,每次可以将一个颜色相同的块变颜色,问最少变几次才能让其变为同色

解题思路:

  我们考虑由于每一次都是把同样颜色的色块进行变色,因此同样颜色的色块可以看成一个点。所以我们先将同一个色块缩成一个点。

  然后我们有一个结论,我们最后的答案就是缩点完成的这棵树的直径+1再除以2.

  我们很容易发现,缩点完成以后的树相邻的两个点颜色一定是不同的,否则就能继续缩。因此我们可以每次选择直径中间的那个点,改变它的颜色,然后它就与周围的那些点融合成为一个新的点,然后再找到中间的,继续重复如上步骤。最后我们会发现,恰好是$(dis+1) / 2$次。这个证明不是很严谨,不过感性地理解一下吧

Code

  细节不多

/*by DennyQi*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define r read()
#define Max(a,b) (((a)>(b))?(a):(b))
#define Min(a,b) (((a)<(b))?(a):(b))
using namespace std;
typedef long long ll;
const int MAXN = ;
const int INF = 0x3f3f3f3f;
const int MOD = ;
inline int read(){
int x = ; int w = ; register unsigned char c = getchar();
for(; c^'-' && (c < '' || c > ''); c = getchar());
if(c == '-') w = -, c = getchar();
for(; c >= '' && c <= ''; c = getchar()) x = (x<<) + (x<<) + c - '';
return x * w;
}
int N,cur_num;
int color[MAXN],nod[MAXN],x[MAXN],y[MAXN],d[MAXN],vis[MAXN];
vector <int> g[MAXN],G[MAXN];
queue <int> q;
inline void add(int u, int v){
g[u].push_back(v);
}
inline void Add(int u, int v){
G[u].push_back(v);
}
void dfs(int u){
int sz = g[u].size(),v;
nod[u] = cur_num;
for(int i = ; i < sz; ++i){
v = g[u][i];
if(!nod[v] && (color[v] == color[u])){
dfs(v);
}
}
}
inline void BFS(int s){
memset(d, 0x3f, sizeof(d));
memset(vis,,sizeof(vis));
d[s] = ;
q.push(s);
vis[s] = ;
int u,sz,v;
while(!q.empty()){
u = q.front();q.pop();
sz = G[u].size();
for(int i = ; i < sz; ++i){
v = G[u][i];
if(!vis[v]){
vis[v] = ;
d[v] = d[u] + ;
q.push(v);
}
}
}
}
int main(){
// freopen(".in","r",stdin);
N=r;
for(int i = ; i <= N; ++i){
color[i]=r;
}
for(int i = ; i < N; ++i){
x[i]=r,y[i]=r;
add(x[i], y[i]);
add(y[i], x[i]);
}
for(int i = ; i <= N; ++i){
if(!nod[i]){
++cur_num;
dfs(i);
}
}
for(int i = ; i < N; ++i){
if(nod[x[i]] != nod[y[i]]){
Add(nod[x[i]], nod[y[i]]);
Add(nod[y[i]], nod[x[i]]);
}
}
/* for(int i = 1; i <= cur_num; ++i){
printf("%d: ", i);
for(int j = 0; j < G[i].size(); ++j){
printf("%d,",G[i][j]);
}
printf("\n");
}*/
BFS();
int _max = -,p;
for(int i = ; i <= cur_num; ++i){
if(d[i] > _max){
_max = d[i];
p = i;
}
}
/* printf("p = %d\n", p);
for(int i = 1; i <= cur_num; ++i){
printf("%d ",d[i]);
}
printf("\n");*/
BFS(p);
_max = -;
for(int i = ; i <= cur_num; ++i){
if(d[i] > _max){
_max = d[i];
}
}
/* for(int i = 1; i <= cur_num; ++i){
printf("%d ",d[i]);
}
printf("\n");
printf("_max = %d\n", _max);*/
printf("%d",(_max+)/);
return ;
}

Codeforces734 E. Anton and Tree的更多相关文章

  1. Codeforces 734E. Anton and Tree 搜索

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

  2. Codeforces Round #379 (Div. 2) E. Anton and Tree 缩点 直径

    E. Anton and Tree 题目连接: http://codeforces.com/contest/734/problem/E Description Anton is growing a t ...

  3. Codeforces Round #379 (Div. 2) E. Anton and Tree 树的直径

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

  4. Anton and Tree

    Anton and Tree 题目链接:http://codeforces.com/contest/734/problem/E DFS/BFS 每一次操作都可以使连通的结点变色,所以可以将连通的点缩成 ...

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

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

  6. Codeforces Round #379 (Div. 2) E. Anton and Tree —— 缩点 + 树上最长路

    题目链接:http://codeforces.com/contest/734/problem/E E. Anton and Tree time limit per test 3 seconds mem ...

  7. 【27.91%】【codeforces 734E】Anton and Tree

    time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  8. Codeforces Round #379 (Div. 2) E. Anton and Tree

    题意: 给一颗树 每个节点有黑白2色 可以使一个色块同事变色,问最少的变色次数. 思路: 先缩点 把一样颜色的相邻点 缩成一个 然后新的树 刚好每一层是一个颜色. 最后的答案就是树的直径/2 不过我用 ...

  9. cf734 E. Anton and Tree

    这个题的题意还是很劲的.搞了好久才知道是怎么变得. (假设已经缩好了点,每次边中间颜色不同的,然后和就和他外面的相同,继续再变这个大的,依次类推,最多就是树的直径D/2) (还是英语水平太弱了(吐槽+ ...

随机推荐

  1. Dijkstra的应用

    每次只涉及一边两端点的极值循环转移应用Dijkstra.

  2. D2. Great Vova Wall (Version 2)

    l链接 [https://codeforces.com/contest/1092/problem/D2] 题意 和D1一样只是不能竖直放了 分析 水平放的话,就只可能是相邻等时才可以,而且你会发现 只 ...

  3. Linux登录MySQL时出现 Can't connect to local MySQL server through socket '/tmp/mysql.sock'解决方法

    在Linux上登录MySQL时出现如下提示,如下图: 通过查找资料了解到: MySQL有两种连接方式: (1)TCP/IP (2)socket 对mysql.sock来说,其作用是程序与mysqlse ...

  4. R语言绘制QQ图

    无论是直方图还是经验分布图,要从比较上鉴别样本是否处近似于某种类型的分布是困难的 QQ图可以帮我们鉴别样本的分布是否近似于某种类型的分布 R语言,代码如下: > qqnorm(w);qqline ...

  5. 通过设置线程池的最小线程数来提高task的效率,SetMinThreads。

    http://www.cnblogs.com/Charltsing/p/taskpoolthread.html task默认对线程的调度是逐步增加的,连续多次运行并发线程,会提高占用的线程数,而等若干 ...

  6. Python文本处理

    文本处理 (一)对文本操作的流程: 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 open(file, mode='r', buffering=None, encoding ...

  7. 每周分享之JS数组的使用

    数组,一堆数字归为一组,就是一个数组,一堆对象放在一个组里,也是一个数组,概念很容易懂,说白了就是一个有限集合. JS数组的语法无法两种,插入和移除(语法自行科普).用处挺常见的,既然数组是一个集合, ...

  8. python中类方法,实例方法,静态方法的作用和区别

      Python中至少有三种比较常见的方法类型,即实例方法,类方法.静态方法.它们是如何定义的呢?如何调用的呢?它们又有何区别和作用呢?且看下文. 首先,这三种方法都定义在类中.下面我先简单说一下怎么 ...

  9. Spring.profile配合Jenkins发布War包,实现开发、测试和生产环境的按需切换

    前两篇不错 Spring.profile实现开发.测试和生产环境的配置和切换 - Strugglion - 博客园https://www.cnblogs.com/strugglion/p/709102 ...

  10. 微信QQ打开网页时提示用浏览器打开

    微信QQ打开网页时提示用浏览器打开 一,需求分析 1.1,使用微信或QQ打开网址时,无法在微信或QQ内打开常用下载软件,手机APP等.故此需要在微信qq里提示 二,功能实现 2.1 html实现 &l ...