前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >YbtOJ 714「点分治」染色计划

YbtOJ 714「点分治」染色计划

作者头像
yzxoi
发布2022-09-19 14:01:01
3130
发布2022-09-19 14:01:01
举报
文章被收录于专栏:OI

YbtOJ 714「点分治」染色计划

题目链接:YbtOJ #714

小 A 有一棵 n 个点的无根树,其中编号为 i 的节点初始颜色为 c_i

一次染色操作可以将某种颜色的点 全部 染成另一种颜色。即可以选择两种颜色 C1,C2,令当前所有等于 C1c_i 变成 C2

求至少执行多少次染色操作,使得存在一种颜色 C,满足对于任意一对 c_x=c_y=C 的点 x,y,树上 x,y 路径中的节点的颜色都是 C

1\le n\le2\times10^51\le k\le n1\le c_i\le k

Solution

点分治。

强制所选的连通块必含分治中心。

从与分治中心同色的所有点开始 BFS,每次将队首的父节点同色的所有点加入队列。

若在过程中出现了当前分治连通块之外的点,则这样得到的答案肯定不会比已有答案更优,直接结束 BFS。否则,就可以在 BFS 结束后更新答案。

这样一来每次 BFS 范围都在分治连通块内,复杂度正确。

Code

代码语言:javascript
复制
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define W while
#define I inline
#define RI register int
#define LL long long
#define Cn const
#define CI Cn int&
#define gc getchar
#define D isdigit(c=gc())
#define pc(c) putchar((c))
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
namespace Debug{
    Tp I void _debug(Cn char* f,Ty t){cerr<<f<<'='<<t<<endl;}
    Ts I void _debug(Cn char* f,Ty x,Ar... y){W(*f!=',') cerr<<*f++;cerr<<'='<<x<<",";_debug(f+1,y...);}
    Tp ostream& operator<<(ostream& os,Cn vector<Ty>& V){os<<"[";for(Cn auto& vv:V) os<<vv<<",";os<<"]";return os;}
    #define gdb(...) _debug(#__VA_ARGS__,__VA_ARGS__)
}using namespace Debug;
namespace FastIO{
    Tp I void read(Ty& x){char c;int f=1;x=0;W(!D) f=c^'-'?1:-1;W(x=(x<<3)+(x<<1)+(c&15),D);x*=f;}
    Ts I void read(Ty& x,Ar&... y){read(x),read(y...);}
    Tp I void write(Ty x){x<0&&(pc('-'),x=-x,0),x<10?(pc(x+'0'),0):(write(x/10),pc(x%10+'0'),0);}
    Tp I void writeln(Cn Ty& x){write(x),pc('\n');}
}using namespace FastIO;
Cn int N=2e5+10,inf=2e9;
int n,m,F[N],c[N],Ans=inf,used[N],Min,cnt,id,sz[N],vis[N];
#define PA pair<int,int>
#define MP make_pair
#define fi first
#define se second
vector<int> G[N],cg[N],vc[N],v;
#define pb push_back
I void GetG(CI x,CI fa){
    RI mx=0;sz[x]=1;for(auto i:G[x]) i^fa&&!vis[i]&&(GetG(i,x),sz[x]+=sz[i],mx=max(mx,sz[i]));
    mx=max(mx,cnt-sz[x]),mx<Min&&(Min=mx,id=x);
}
I void Get(CI x,CI fa){F[x]=fa,v.pb(x);for(auto i:G[x]) i^fa&&!vis[i]&&(Get(i,x),0);}
I void Cle(CI x,CI fa){F[x]=0;for(auto i:G[x]) i^fa&&!vis[i]&&(Cle(i,x),0);}
queue<int> q;
I void Dfs(CI x){
    RI i,j,X=0;vis[x]=1;v.clear(),Get(x,0);for(auto i:v) vc[c[i]].pb(i),used[c[i]]=0;
    W(!q.empty()) q.pop();used[c[x]]=1,q.push(c[x]);W(!q.empty()){
        RI u=q.front();q.pop(),X++;if(cg[u].size()!=vc[u].size()){X=inf;break ;}
        for(auto i:vc[u]) F[i]&&(!used[c[F[i]]]&&(q.push(c[F[i]]),used[c[F[i]]]=1));
    }Ans=min(Ans,X);for(auto i:v) vc[c[i]].clear();Cle(x,0);
    for(auto i:G[x]) !vis[i]&&(cnt=sz[i],Min=inf,GetG(i,0),Dfs(id),0);
}
int main(){
    freopen("color.in","r",stdin),freopen("color.out","w",stdout);
    RI i,x,y;for(read(n,m),i=1;i<n;i++) read(x,y),G[x].pb(y),G[y].pb(x);
    for(i=1;i<=n;i++) read(c[i]),cg[c[i]].pb(i);Min=inf,cnt=n,GetG(1,0),Dfs(id);
    return writeln(Ans-1),0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-02-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • YbtOJ 714「点分治」染色计划
    • Solution
      • Code
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档