Codeforces 734E. Anton and Tree By Assassin 缩点+树的最大直径
2016-11-30 19:30
447 查看
题意就不多加赘述了,说白了就是每一次可以反转任意连通块儿,这个连通块儿必须满足相连且花色相同,问你最少的反转次数。
思路:一看题目思路其实很清楚了,我们为了缩小数据规模,利用缩点将一个连同块儿化成一个点,之后我们一定可以得到一个树,因为原题就是一个树,之后我们只需要找到树的最大直径就行了。
步骤1:缩点
步骤2:求树的最大直径(其实就是两次搜索,因为第一次从任意点出发找到最远的一个点,那么这个点一定是树直径上两端的一个点,第二次再从这个点出发找到最远的点的距离就是树的直径了。)
第一次写缩点,丑了点。。。
思路:一看题目思路其实很清楚了,我们为了缩小数据规模,利用缩点将一个连同块儿化成一个点,之后我们一定可以得到一个树,因为原题就是一个树,之后我们只需要找到树的最大直径就行了。
步骤1:缩点
步骤2:求树的最大直径(其实就是两次搜索,因为第一次从任意点出发找到最远的一个点,那么这个点一定是树直径上两端的一个点,第二次再从这个点出发找到最远的点的距离就是树的直径了。)
第一次写缩点,丑了点。。。
#include<bits/stdc++.h> #define input freopen("input.txt","r",stdin) using namespace std; const int maxn = 200002; vector<int>vec[maxn],change[maxn]; int vis[maxn]={0},color[maxn]={0},belong[maxn]={0}; // belong代表改点归并到第几个缩点 int n,suo_size=0,ans=maxn,fathur=0; void dfs(int pos,int number){ int i; vis[pos]=1; belong[pos]=number; for(i=0;i<vec[pos].size();i++){ if(vis[vec[pos][i]]==0&&color[vec[pos][i]]==color[pos]){ dfs(vec[pos][i],number); } } } void DFS(int pos){ int i; vis[pos]=1; for(i=0;i<vec[pos].size();i++){ if(vis[vec[pos][i]]==0&&color[vec[pos][i]]==color[pos]){ DFS(vec[pos][i]); } else if(vis[vec[pos][i]]==0&&color[vec[pos][i]]!=color[pos]){ change[belong[vec[pos][i]]].push_back(belong[pos]); change[belong[pos]].push_back(belong[vec[pos][i]]); } } } void dps(int pos,int length){ int i,flag=1; vis[pos]=1; for(i=0;i<change[pos].size();i++){ if(vis[change[pos][i]]==0){ dps(change[pos][i],length+1); flag=0; } } if(flag==1){ if(ans<length){ ans=length; fathur=pos; } } return ; } int main(){ int i,j,l,r; while(scanf("%d",&n)!=EOF){ for(i=1;i<=n;i++) scanf("%d",&color[i]); for(i=1;i<=n-1;i++){ scanf("%d%d",&l,&r); vec[l].push_back(r); vec[r].push_back(l); } memset(vis,0,sizeof(vis)); //其实大多ACM写成一次处理的,我喜欢加上EOF操作,所以vis要经常初始化,就慢了 for(suo_size=0,i=1;i<=n;i++){ //这次dfs将连通块儿缩到一个点 if(vis[i]==0){ suo_size++; dfs(i,suo_size); } } memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++){ //这次DFS将缩点后树连接起来 if(vis[i]==0) DFS(i); } memset(vis,0,sizeof(vis)); ans=0; fathur=0; //求树的直径 dps(1,0); ans=0; //第一次的ans求出来没用。。。 memset(vis,0,sizeof(vis)); //记得初始化 访问数组 dps(fathur,0); cout<<(ans+1)/2<<endl; //结果先加1因为有奇偶情况,ans求的是两端最远距离,还要加上自己才是直径 } return 0; }
相关文章推荐
- codeforces 734E (树的最大直径)
- Codeforces734E【缩点+树的直径】
- Codeforces 734E Anton and Tree【并查集缩点||DFS缩点+树的直径】
- Codeforces 734E 树的直径+缩点
- codeforces 734e(连通分量缩点)
- 【codeforces 734E】Anton and Tree【缩点+DP】
- 【CodeForces734E】【缩点】Anton and Tree 题解
- Codeforces 839E Mother of Dragons(最大团)
- 【HDU】4971 A simple brute force problem. 强连通缩点+最大权闭合子图
- 【最大费用最大流】【Codeforces】164C - Machine Programming
- codeforces 51F Caterpillar tarjan缩点+dfs
- [HDOJ4612]Warm up(双连通分量,缩点,树直径)
- Codeforces 592D Super M 【求解包含若干个点的最小树 + 树的直径】
- Codeforces 337D Book of Evil 树状DP 或 BFS找子树直径端点
- Codeforces 949C Data Center Maintenance 缩点+拓扑
- Codeforce Round #379 (Div. 2) 734 E Anton and Tree(tree 缩点 树的直径 )
- 二维凸包模板(凸包重心,周长,面积,直径,最大三角形,最小环绕矩形)
- 2017ccpc全国邀请赛(湖南湘潭) H. Highway (最大生成树)(树的直径)
- 思路题,树的直径(Anton and Tree,cf 734E)
- leetcode解题之543. Diameter of Binary Tree Java版 (二叉树的最大直径)